如何使用setuptools/distutils包含包数据?

195 投票
14 回答
139972 浏览
提问于 2025-04-17 02:53

在使用setuptools的时候,我发现安装程序无法获取任何的 package_data 文件。我看到的所有资料都说下面的做法是正确的。有人能给点建议吗?

setup(
   name='myapp',
   packages=find_packages(),
   package_data={
      'myapp': ['data/*.txt'],
   },
   include_package_data=True,
   zip_safe=False,
   install_requires=['distribute'],
)

这里的 myapp/data/ 是数据文件的存放位置。

14 个回答

24

根据@Joe的建议,去掉了include_package_data=True这一行,也对我有用。

再详细说一下,我没有 MANIFEST.in文件。我使用的是Git,而不是CVS。

我的代码库大致是这个样子的:

/myrepo
    - .git/
    - setup.py
    - myproject
        - __init__.py
        - some_mod
            - __init__.py
            - animals.py
            - rocks.py
        - config
            - __init__.py
            - settings.py
            - other_settings.special
            - cool.huh
            - other_settings.xml
        - words
            - __init__.py
            word_set.txt

setup.py文件内容:

from setuptools import setup, find_packages
import os.path

setup (
    name='myproject',
    version = "4.19",
    packages = find_packages(),  
    # package_dir={'mypkg': 'src/mypkg'},  # didnt use this.
    package_data = {
        # If any package contains *.txt or *.rst files, include them:
        '': ['*.txt', '*.xml', '*.special', '*.huh'],
    },

#
    # Oddly enough, include_package_data=True prevented package_data from working.
    # include_package_data=True, # Commented out.
    data_files=[
#               ('bitmaps', ['bm/b1.gif', 'bm/b2.gif']),
        ('/opt/local/myproject/etc', ['myproject/config/settings.py', 'myproject/config/other_settings.special']),
        ('/opt/local/myproject/etc', [os.path.join('myproject/config', 'cool.huh')]),
#
        ('/opt/local/myproject/etc', [os.path.join('myproject/config', 'other_settings.xml')]),
        ('/opt/local/myproject/data', [os.path.join('myproject/words', 'word_set.txt')]),
    ],

    install_requires=[ 'jsonschema',
        'logging', ],

     entry_points = {
        'console_scripts': [
            # Blah...
        ], },
)

我运行python setup.py sdist来生成源代码包(还没尝试过二进制包)。

在一个全新的虚拟环境中,我得到了一个myproject-4.19.tar.gz文件,接着我使用了

(venv) pip install ~/myproject-4.19.tar.gz
...

除了所有东西都安装到我的虚拟环境的site-packages目录外,那些特殊的数据文件被安装到了/opt/local/myproject/data/opt/local/myproject/etc目录。

45

我之前也遇到过这个问题。解决办法就是简单地去掉 include_package_data=True 这一行。

这里阅读后,我明白了 include_package_data 的作用是为了包含来自版本控制的文件,而不是单纯的“包含包数据”,这名字有点误导。从文档中可以看到:

[include_package_data] 的数据文件必须在 CVS 或 Subversion 控制下

...

如果你想更细致地控制包含哪些文件(比如,如果你的包目录里有文档文件,想把它们排除在安装之外),那么你可以使用 package_data 这个参数。

去掉这个参数后问题就解决了,这也是为什么当你切换到 distutils 时也能正常工作,因为它不需要这个参数。

379

我知道这个问题已经很老了,但对于通过谷歌找到这里的人来说,package_data 是个很糟糕的误导。它只在构建 二进制 包时使用(也就是运行 python setup.py bdist ...),而在构建源包时(运行 python setup.py sdist ...)却不使用。这实在是太荒谬了——人们本来会期待,构建源分发包时,应该能得到一堆文件,这些文件可以发给别人,让他们来构建二进制分发包。

无论如何,使用 MANIFEST.in 这个文件,可以同时适用于二进制和源分发包。

撰写回答