如何在setuptools / distribute中包含软件包数据?

问题:如何在setuptools / distribute中包含软件包数据?

使用setuptools / distribute时,我无法使安装程序提取任何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/数据文件的位置在哪里。

When using setuptools, I can not get the installer to pull in any package_data files. Everything I’ve read says that the following is the correct way to do it. Can someone please advise?

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

where myapp/data/ is the location of the data files.


回答 0

我知道这是一个老问题,但人们发现这里通过谷歌自己的方式: package_data是低了下来,肮脏的谎言。它仅在构建二进制软件包(python setup.py bdist ...)时使用,在构建源软件包(python setup.py sdist ...)时不使用。当然,这是荒谬的-人们希望构建源代码分发将导致文件集合,这些文件可以发送给其他人来构建二进制分发。

在任何情况下,使用MANIFEST.in将工作二进制和源分布。

I realize that this is an old question, but for people finding their way here via Google: package_data is a low-down, dirty lie. It is only used when building binary packages (python setup.py bdist ...) but not when building source packages (python setup.py sdist ...). This is, of course, ridiculous — one would expect that building a source distribution would result in a collection of files that could be sent to someone else to built the binary distribution.

In any case, using MANIFEST.in will work both for binary and for source distributions.


回答 1

我只是有同样的问题。解决的方法是简单地删除include_package_data=True

这里阅读之后,我意识到它include_package_data旨在包含来自版本控制的文件,而不是顾名思义仅包含“ include package data”。从文档:

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

如果要对包含的文件进行更细粒度的控制(例如,如果您的软件包目录中有文档文件,并希望将其从安装中排除),则也可以使用package_data关键字。

把那个参数排除掉可以解决这个问题,这恰好是为什么当您切换到distutils时它也可以工作的原因,因为它不接受那个参数。

I just had this same issue. The solution, was simply to remove include_package_data=True.

After reading here, I realized that include_package_data aims to include files from version control, as opposed to merely “include package data” as the name implies. From the docs:

The data files [of include_package_data] must be under CVS or Subversion control

If you want finer-grained control over what files are included (for example, if you have documentation files in your package directories and want to exclude them from installation), then you can also use the package_data keyword.

Taking that argument out fixed it, which is coincidentally why it also worked when you switched to distutils, since it doesn’t take that argument.


回答 2

遵循@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

Following @Joe ‘s recommendation to remove the include_package_data=True line also worked for me.

To elaborate a bit more, I have no MANIFEST.in file. I use Git and not CVS.

Repository takes this kind of shape:

/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...
        ], },
)

I run python setup.py sdist for a source distrib (haven’t tried binary).

And when inside of a brand new virtual environment, I have a myproject-4.19.tar.gz, file, and I use

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

And other than everything getting installed to my virtual environment’s site-packages, those special data files get installed to /opt/local/myproject/data and /opt/local/myproject/etc.


回答 3

include_package_data=True 为我工作。

如果你使用git,请记住,包括setuptools-gitinstall_requires。远没有拥有Manifest或包含所有路径package_data(在我的情况下,它是具有各种静态特性的django应用程序)那么无聊

(粘贴了我的评论,就像k3-rnc所说的那样,实际上是有帮助的)

include_package_data=True worked for me.

If you use git, remember to include setuptools-git in install_requires. Far less boring than having a Manifest or including all path in package_data ( in my case it’s a django app with all kind of statics )

( pasted the comment I made, as k3-rnc mentioned it’s actually helpful as is )


回答 4

更新:此答案是旧的,该信息不再有效。所有setup.py配置均应使用import setuptools。我在https://stackoverflow.com/a/49501350/64313中添加了更完整的答案


我通过切换到distutils解决了这个问题。似乎已弃用和/或破坏了分发。

from distutils.core import setup

setup(
   name='myapp',
   packages=['myapp'],
   package_data={
      'myapp': ['data/*.txt'],
   },
)

Update: This answer is old and the information is no longer valid. All setup.py configs should use import setuptools. I’ve added a more complete answer at https://stackoverflow.com/a/49501350/64313


I solved this by switching to distutils. Looks like distribute is deprecated and/or broken.

from distutils.core import setup

setup(
   name='myapp',
   packages=['myapp'],
   package_data={
      'myapp': ['data/*.txt'],
   },
)

回答 5

古老的问题,然而… python的软件包管理确实有很多不足之处。因此,我有在本地使用pip安装到指定目录的用例,很惊讶package_data和data_files路径都无法解决。我不希望再向仓库添加另一个文件,所以最终我利用了data_files和setup.py选项–install-data;。像这样的东西

pip install . --install-option="--install-data=$PWD/package" -t package  

Ancient question and yet… package management of python really leaves a lot to be desired. So I had the use case of installing using pip locally to a specified directory and was surprised both package_data and data_files paths did not work out. I was not keen on adding yet another file to the repo so I ended up leveraging data_files and setup.py option –install-data; something like this

pip install . --install-option="--install-data=$PWD/package" -t package  

回答 6

将包含软件包数据的文件夹移到module文件夹为我解决了这个问题。

看到这个问题:MANIFEST.in在“ python setup.py install”上被忽略-没有安装数据文件?

Moving the folder containing the package data into to module folder solved the problem for me.

See this question: MANIFEST.in ignored on “python setup.py install” – no data files installed?


回答 7

我在几天中遇到了同样的问题,但是即使一切都变得混乱,这个线程也无法为我提供帮助。因此,我进行了研究,发现了以下解决方案:

基本上在这种情况下,您应该执行以下操作:

from setuptools import setup

setup(
   name='myapp',
   packages=['myapp'],
   package_dir={'myapp':'myapp'}, # the one line where all the magic happens
   package_data={
      'myapp': ['data/*.txt'],
   },
)

完整的其他stackoverflow答案在这里

I had the same problem for a couple of days but even this thread wasn’t able to help me as everything was confusing. So I did my research and found the following solution:

Basically in this case, you should do:

from setuptools import setup

setup(
   name='myapp',
   packages=['myapp'],
   package_dir={'myapp':'myapp'}, # the one line where all the magic happens
   package_data={
      'myapp': ['data/*.txt'],
   },
)

The full other stackoverflow answer here


回答 8

只需删除该行:

include_package_data=True,

从您的安装脚本中,它将正常工作。(刚刚通过最新的setuptools测试。)

Just remove the line:

include_package_data=True,

from your setup script, and it will work fine. (Tested just now with latest setuptools.)


回答 9

使用setup.cfg(setuptools≥30.3.0)

从setuptools 30.3.0(2016年12月8日发布)开始,您可以保持setup.py很小的规模并将配置移动到setup.cfg文件中。使用这种方法,您可以将包数据放在以下[options.package_data]部分中:

[options.package_data]
* = *.txt, *.rst
hello = *.msg

在这种情况下,您setup.py可以做到:

from setuptools import setup
setup()

有关更多信息,请参阅使用setup.cfg文件配置安装程序

一些关于setup.cfgPEP 518中pyproject.toml提议的弃用赞成的说法,但从2020年2月21日起这仍然是临时的。

Using setup.cfg (setuptools ≥ 30.3.0)

Starting with setuptools 30.3.0 (released 2016-12-08), you can keep your setup.py very small and move the configuration to a setup.cfg file. With this approach, you could put your package data in an [options.package_data] section:

[options.package_data]
* = *.txt, *.rst
hello = *.msg

In this case, your setup.py can be as short as:

from setuptools import setup
setup()

For more information, see configuring setup using setup.cfg files.

There is some talk of deprecating setup.cfg in favour of pyproject.toml as proposed in PEP 518, but this is still provisional as of 2020-02-21.