次のプロジェクトレイアウトを見てみましょう。
$ ls -R .
.:
package setup.py
./package:
__init__.py dir file.dat module.py
./package/dir:
tool1.dat tool2.dat
そして、setup.py
の次のコンテンツ:
$ cat setup.py
from distutils.core import setup
setup(name='pyproj',
version='0.1',
packages=[
'package',
],
package_data={
'package': [
'*',
'dir/*',
],
},
)
ご覧のとおり、Python以外のすべてのファイルをpackage/
およびpackage/dir/
ディレクトリに含めたいと思います。ただし、setup.py install
を実行すると、次のエラーが発生します。
$ python setup.py install
running install
running build
running build_py
creating build
creating build/lib
creating build/lib/package
copying package/module.py -> build/lib/package
copying package/__init__.py -> build/lib/package
error: can't copy 'package/dir': doesn't exist or not a regular file
何が得られますか?
package_data
では、'*'
グロブがpackage/dir
自体と一致し、そのディレクトリをファイルとしてコピーしようとすると、失敗します。ディレクトリpackage/dir
と一致しないグロブを見つけ、次の行に沿ってsetup.py
を書き換えます。
from distutils.core import setup
setup(name='pyproj',
version='0.1',
packages=[
'package',
],
package_data={
'package': [
'*.dat',
'dir/*'
],
},
)
あなたの例では、それは'*'
を'*.dat'
に変更するだけですが、おそらくそれ以上にグロブを改良する必要がありますが、'dir'
と一致しないことを確認してください
Distutilsの代わりに Distribute を使用できます。これは基本的に同じように機能し(ほとんどの場合、setup.pyを変更する必要はありません)、exclude_package_dataオプションを提供します。
from distribute_setup import use_setuptools
use_setuptools()
from setuptools import setup
setup(name='pyproj',
version='0.1',
packages=[
'package',
],
package_data={
'package': [
'*.dat',
'dir/*'
],
},
exclude_package_data={
'package': [
'dir'
],
},
)
理由はよくわかりませんが、トラブルシューティングを行った結果、名前にドットが含まれているディレクトリの名前を変更すると問題が解決することがわかりました。例えば。
chart.js-2.4.0 => chart_js-2_4_0
注:私はPython 2.7.10、SetupTools 12.2
必要なすべてのファイルを提供する関数を作成しました
def find_files(directory, strip):
"""
Using glob patterns in ``package_data`` that matches a directory can
result in setuptools trying to install that directory as a file and
the installation to fail.
This function walks over the contents of *directory* and returns a list
of only filenames found. The filenames will be stripped of the *strip*
directory part.
"""
result = []
for root, dirs, files in os.walk(directory):
for filename in files:
filename = os.path.join(root, filename)
result.append(os.path.relpath(filename, strip))
return result
そしてそれをpackage_data
の補強として使用しました