setup.pyでPython以外のファイルを含める


200

setup.pyコードの一部ではないファイルを含めるにはどうすればよいですか?(具体的には、ライセンスファイルですが、それ以外の場合もあります。)

ファイルの場所を制御できるようにしたい。元のソースフォルダーでは、ファイルはパッケージのルートにあります。(つまり、最上位と同じレベルにあり__init__.pyます。)パッケージは、オペレーティングシステムに関係なく、インストールされたときに、その場所に正確に残しておく必要があります。それ、どうやったら出来るの?


現時点ではどのようにしていますか?前の質問は、ライセンスファイルを追加する方法に精通していることを示しているので、「機能しない」コードは何ですか?
SilentGhost 2009年

2
data_files = [('', ['lgpl2.1_license.txt',]),]Python26フォルダーに配置します。
Ram Rachum、2009年

いくつかの否定的なフィードバックの後、私はもう一度あなたの質問を読み、何が欠けているのかを理解しました。追加のモジュール(setuptoolsや配布など)を必要としない、ハッキングのないソリューションを提供するために私の回答を更新しました。
Evan Plaice、2011年

エヴァンありがとう。ただし、setuptoolsは非常に普及しているため、私はそれを使用してもまったく問題ありません。
Ram Rachum、2010年

回答:


224

おそらくこれを行うための最良の方法は、setuptools package_dataディレクティブを使用することです。これはの代わりにsetuptools(またはdistribute)を使用することを意味しますがdistutils、これは非常にシームレスな「アップグレード」です。

以下は完全な(ただしテストされていない)例です。

from setuptools import setup, find_packages

setup(
    name='your_project_name',
    version='0.1',
    description='A description.',
    packages=find_packages(exclude=['ez_setup', 'tests', 'tests.*']),
    package_data={'': ['license.txt']},
    include_package_data=True,
    install_requires=[],
)

ここで重要な特定の行に注意してください:

package_data={'': ['license.txt']},
include_package_data=True,

package_dataあるdictパターンのリストにパッケージ名(空=すべてのパッケージ)(グロブを含めることができる)の。たとえば、パッケージ内のファイルのみを指定する場合は、次のようにすることもできます。

package_data={'yourpackage': ['*.txt', 'path/to/resources/*.txt']}

ここでの解決策は間違いありません、あなた以外名前を変更するためにpyAを使用してファイルを.py拡張子の。

詳細については、Ian Bickingのプレゼンテーションを参照してください。

更新:別の[より良い]アプローチ

ソース配布(sdist)のコンテンツを制御し、パッケージの外部にファイル(たとえば、最上位ディレクトリ)を置きたいだけの場合にうまく機能する別のアプローチは、MANIFEST.inファイルを追加することです。このファイルの形式については、Pythonのドキュメントを参照してください。

この応答を書いて以来MANIFEST.in、ソース配布(tar.gz)に必要なファイルが含まれていることを確認するだけで、通常はを使用した方がイライラすることは少ないことがわかりました。

たとえばrequirements.txt、最上位のfrom を含める場合は、最上位の「データ」ディレクトリを再帰的に含めます。

include requirements.txt
recursive-include data *

それにもかかわらず、これらのファイルをインストール時にsite-packages内のパッケージのフォルダーにコピーするinclude_package_data=Trueには、setup()関数に供給する必要があります。詳細については、非コードファイルの追加を参照してください。


5
package_dataは、Python 2.3以降の純粋なdistutilsセットアップスクリプトでも使用できます。
エリックアラウージョ

15
この答えは賢明に見えますが、私にはうまくいきません。package_dataは信頼性が低いことで悪名高く(ファイルをsdistに追加してインストールするために、MANIFEST.inとsetup.pyの調整が必要です)、この回答の作成者は「テストされていません」と述べています。他にそれが彼らのために働くかどうか確認しますか?私のLICENSEファイルはsdistに含まれていますが、「python setup.py install」または「pip install Package」を実行してもインストールされません
Jonathan Hartley

11
Ian Bickingのプレゼンテーションは、パッケージ内にあるファイルのパッケージデータをインストールする方法のみを示しています。LICENSEファイルはプロジェクトの最上位にあります。つまり、どのパッケージにもありません。それでもpackage_dataを使用できますか?data_filesを使用すると、ファイルがシステム全体の場所に配置されるため、スターターではありません。私のプロジェクトに関連付けられていません。さらに悪いことに、同じsdistから「setup.py install」または「pip install」を実行するかどうかによって場所が変わります。
ジョナサンハートレイ

8
私にとってそれが機能しない理由は、ファイルがどのパッケージ内にも配置されていないためだと思います-これはリポジトリの最上位にあるLICENSEファイルであるため、「package_data」を使用してインストールできません
ジョナサンハートレー

7
この答えは私にはうまくいきません。追加のファイルがtarballに入れられない...
lpapp

44

あなたが説明していることを達成するには、2つのステップを踏みます...

  • ファイルをソースtarballに追加する必要があります
  • データファイルをソースパスにインストールするには、setup.pyを変更する必要があります

手順1:ファイルをソースtarballに追加するには、マニフェストに含めます

setup.pyを含むフォルダーにMANIFESTテンプレートを作成します

MANIFESTは基本的に、ソースtarballに含まれるすべてのファイルのリストを含むテキストファイルです。

私のプロジェクトのマニフェストは次のようになります。

  • CHANGELOG.txt
  • INSTALL.txt
  • LICENSE.txt
  • pypreprocessor.py
  • README.txt
  • setup.py
  • test.py
  • TODO.txt

注:sdist 一部のファイルを自動的追加します、何を行うか、または行わないかを予測するのではなく、ファイルを確実に明示的に指定することをお勧めます。

手順2:データファイルをソースフォルダーにインストールするには、setup.pyを変更します。

データファイル(LICENSE.txt)をソースインストールフォルダーに追加しようとしているので、データインストールパスをソースインストールパスと一致するように変更する必要があります。デフォルトでは、データファイルはソースファイルとは異なる場所にインストールされるため、これが必要です。

ソースインストールディレクトリと一致するようにデータインストールディレクトリを変更するには...

次のコマンドを使用して、distutilsからインストールディレクトリ情報を取得します。

from distutils.command.install import INSTALL_SCHEMES

ソースインストールディレクトリと一致するようにデータインストールディレクトリを変更します。

for scheme in INSTALL_SCHEMES.values():
    scheme['data'] = scheme['purelib']

そして、データファイルと場所をsetup()に追加します。

data_files=[('', ['LICENSE.txt'])]

注:上記の手順は、拡張ライブラリを必要とせずに、標準的な方法で説明したとおりに実行する必要があります。


10
マニフェストは、ソースtarball(sdistによって作成)に含まれている制御ファイルのみです。そこにリストされているファイルはインストールされません。
David Cournapeau、2010年

@David自分の最初のアプローチがどれだけ離れているかわからなかった。追加のサードパーティライブラリを必要とせずに、質問が何を求めているかを達成するために、正解に回答を更新しました。
Evan Plaice、2010年

3
@Éric特別な理由はありますか?また、サードパーティのパッケージ(setup_toolsなど)を動作させる必要のない、実行可能なインストーラーの代替案はありますか。pythonのバニラインストールに含まれ、PYPI用のモジュールを構築していたため、setuptoolsではなくdistutilsを選択しました。distutils2を使用してこれを行うより良い方法があるはずですが、私はかなり長い間Pythonに触れていなかったので、方法がわかりません。あなたはdistutils2に精通しているように見えるので、適切なdistutils2を使用することは私たちの残りの部分に利益をもたらすと思います。
エヴァンプレイス、

6
他のスレッドで述べたpackage_dataように、ファイルがパッケージにない場合は機能しません。
Gringo Suave 2013年

2
@ÉricAraujo:他に方法がないため、このソリューションを使用することは悪い考えではありません。これはdistutilsの設計としては良くありません。しかし、それは多くのことを壊すので、決して変わらない事実上の公開APIです。distutils2がより良い推奨方法を提供することを期待しましょう。
anatly techtonik 2013年


7

質問の1つにコメントを投稿したかったのですが、その評判が十分ではありません>。>

これは私のために働いたものです(ドキュメントを参照した後それを思いついた):

package_data={
    'mypkg': ['../*.txt']
},

include_package_data: False

最後の行は、奇妙なことに、私にとっても非常に重要でした(このキーワード引数を省略してもかまいません。同じように機能します)。

これは、トップレベルまたはルートディレクトリ(パッケージから1レベル上の)にあるすべてのテキストファイルをコピーします mypkg配布ことです。

お役に立てれば!


を作成する必要がない方法を探していましたがMANIFEST.in、これでうまくいきました。最後の行も私にとって重要でした。私のセリフはinclude_package_data=False, package_data={ "": ["../CHANGELOG.md"] },
メンダック

7

ステップ1:を作成するMANIFEST.in setup.pyと同じフォルダーにファイルを

手順2:追加するファイルへの相対パスを含めるMANIFEST.in

include README.rst
include docs/*.txt
include funniest/data.json

手順3:これらのファイルをサイトパッケージにコピーinclude_package_data=Trueするsetup()関数を設定する

参考はこちら。


6

それは2019年であり、ここが機能しています-あちこちでアドバイスにもかかわらず、ドキュメントの途中でインターネット上で見つけたものはを使用してsetuptools_scmに渡され、にオプションとして渡されますsetuptools.setup。これには、VCSでバージョン管理されているデータファイル(gitまたはその他)がwheelパッケージに含まれ、gitリポジトリから "pip install"を実行して、それらのファイルをまとめます。

したがって、「setup.py」のセットアップ呼び出しにこれらの2行を追加しました。追加のインストールやインポートは必要ありません。

    setup_requires=['setuptools_scm'],
    include_package_data=True,

package_dataまたはMANIFEST.inファイルに手動でリストする必要はありません。バージョン管理されている場合、パッケージに含まれています。「setuptools_scm」に関するドキュメントでは、コミット位置からのバージョン番号の作成に重点が置かれ、データファイルの追加の非常に重要な部分は無視されます。(中間ホイールファイルの名前が「* 0.2.2.dev45 + g3495a1f」であるか、入力したハードコードされたバージョン番号「0.3.0dev0」を使用するかどうかは問題ありませんが、プログラムに重要なファイルを残して、背後での作業はやや重要です)


5

setup.pyのsetup(:

setup(
   name = 'foo library'
   ...
  package_data={
   'foolibrary.folderA': ['*'],     # All files from folder A
   'foolibrary.folderB': ['*.txt']  #All text files from folder B
   },

1
これは実際にはOPの目標を達成するために何もしません。何を書き込んでpackage_datasetup.py install、インストールコマンド自体を変更しない限り、何の影響も受けません。これらのファイルがパッケージディレクトリの下にある場合を除き、これは通常は避けたいものです。
wvxvw 2018

3

ここに私のために働いたより簡単な答えがあります。

まず、上記のPython Devのコメントによると、setuptoolsは必要ありません。

package_data is also available to pure distutils setup scripts 
since 2.3.  Éric Araujo

パッケージにsetuptools要件を課すと、それもインストールする必要があるため、これは素晴らしいことです。要するに:

from distutils.core import setup

setup(
    # ...snip...
    packages          = ['pkgname'],
    package_data      = {'pkgname': ['license.txt']},
)

1
ディレクトリpkgameが存在しないという
Anthony Kong

1

Centos 6でPython 2.7を使用して動作しているのを確認したいだけです。上記のようにpackage_dataまたはdata_filesを追加してもうまくいきませんでした。必要なファイルを含むMANIFEST.INを追加して、非Pythonファイルをtarballに入れましたが、RPM経由でターゲットマシンにインストールしませんでした。

最終的に、setup / setuptoolsの「オプション」を使用して、ソリューションにファイルを取り込むことができました。オプションファイルを使用すると、仕様ファイルのさまざまなセクションをsetup.pyから変更できます。次のように。

from setuptools import setup


setup(
    name='theProjectName',
    version='1',
    packages=['thePackage'],
    url='',
    license='',
    author='me',
    author_email='me@email.com',
    description='',
    options={'bdist_rpm': {'install_script': 'filewithinstallcommands'}},
)

ファイル-MANIFEST.in:

include license.txt

file-filewithinstallcommands:

mkdir -p $RPM_BUILD_ROOT/pathtoinstall/
#this line installs your python files
python setup.py install -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES
#install license.txt into /pathtoinstall folder
install -m 700 license.txt $RPM_BUILD_ROOT/pathtoinstall/
echo /pathtoinstall/license.txt >> INSTALLED_FILES

-12

回避策を考え出した:私は私の名前を変更lgpl2.1_license.txtlgpl2.1_license.txt.py、テキストの周りにいくつかのトリプル引用符を置きます。これで、data_filesオプションを使用したり、絶対パスを指定したりする必要はありません。それをPythonモジュールにすることは醜いことですが、絶対パスを指定するよりも醜いとは思いません。


7
私の投稿を参照してください。それは醜い必要はありません。パッケージをセットアップするための優れたドキュメントを見つけるのは難しいので、ネット上で良い例を見つけるのは難しいだけです。
Evan Plaice
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.