89

如何控制轮子中包含哪些文件?它似乎MANIFEST.in不被python setup.py bdist_wheel.

更新

我对从源代码压缩包和轮子安装之间的区别是错误的。源代码分发包含 中指定的文件MANIFEST.in,但安装的包只有 python 文件。需要采取步骤来识别应安装的其他文件,无论安装是通过源代码分发、egg 还是 wheel。也就是说,额外的包文件需要package_data ,而包外的文件(如命令行脚本或系统配置文件)需要data_files

原始问题

我有一个项目,我一直在用python setup.py sdist它来构建我的包,MANIFEST.in控制包含和排除的文件,以及pyromacheck-manifest来确认我的设置。

我最近将它转换为双 Python 2 / 3 代码,并添加了一个 setup.cfg

[bdist_wheel]
universal = 1

我可以用 构建一个轮子python setup.py bdist_wheel,它似乎是一个万能轮子。但是,它不包括MANIFEST.in.

安装什么?

我挖得更深了,现在对包装和轮子有了更多的了解。这是我学到的:

我将两个包文件上传到PyPi 上的 multigtfs 项目

  • multigtfs-0.4.2.tar.gz- 源 tar 球,其中包括MANIFEST.in.
  • multigtfs-0.4.2-py2.py3-none-any.whl- 有问题的二进制分布。

我创建了两个新的虚拟环境,都使用 Python 2.7.5,并安装了每个包 ( pip install multigtfs-0.4.2.tar.gz)。这两个环境几乎相同。它们有不同.pyc的文件,即“编译”的 Python 文件。有日志文件记录磁盘上的不同路径。从源 tar 球安装包括一个文件夹multigtfs-0.4.2-py27.egg-info,详细说明安装,而轮子安装有一个multigtfs-0.4.2.dist-info文件夹,其中包含该过程的详细信息。但是从使用multigtfs项目的代码来看,两种安装方式并没有什么区别。

明确地说,我的测试也没有使用 .zip 文件,因此测试套件将失败:

$ django-admin startproject demo
$ cd demo
$ pip install psycopg2  # DB driver for PostGIS project
$ createdb demo         # Create PostgreSQL database
$ psql -d demo -c "CREATE EXTENSION postgis" # Make it a PostGIS database 
$ vi demo/settings.py   # Add multigtfs to INSTALLED_APPS,
                        # Update DATABASE to set ENGINE to django.contrib.gis.db.backends.postgis
                        # Update DATABASE to set NAME to test
$ ./manage.py test multigtfs.tests  # Run the tests
...
IOError: [Errno 2] No such file or directory: u'/Users/john/.virtualenvs/test/lib/python2.7/site-packages/multigtfs/tests/fixtures/test3.zip'

指定附加文件

使用答案中的建议,我添加了一些额外的指令setup.py

from __future__ import unicode_literals
# setup.py now requires some funky binary strings
...
setup(
    name='multigtfs',
    packages=find_packages(),
    package_data={b'multigtfs': ['test/fixtures/*.zip']},
    include_package_data=True,
    ...
)

这会将 zip 文件(以及 README)安装到文件夹中,并且测试现在可以正常运行。感谢您的建议!

4

6 回答 6

53

你试过package_data在你的setup.py? MANIFEST.in似乎针对python版本<= 2.6,我不确定更高版本是否会查看它。

在探索https://github.com/pypa/sampleproject之后,他们MANIFEST.in说:

# If using Python 2.6 or less, then have to include package data, even though
# it's already declared in setup.py
include sample/*.dat

这似乎意味着这种方法已经过时了。同时,在setup.py他们声明中:

setup(
    name='sample',
    ...
    # If there are data files included in your packages that need to be
    # installed, specify them here.  If using Python 2.6 or less, then these
    # have to be included in MANIFEST.in as well.
    include_package_data=True,
    package_data={
        'sample': ['package_data.dat'],
    },
    ...
)

(我不确定他们为什么选择通配符MANIFEST.in和文件名setup.py。他们指的是同一个文件)

这与更简单一起,似乎再次暗示该package_data路线优于该MANIFEST.in方法。好吧,除非你必须支持 2.6,否则我会向你祈祷。

于 2014-09-21T22:52:10.427 回答
43

MANIFEST.in在您进行任何更改之前setup.py您必须删除旧的输出目录。Setuptools 正在缓存一些数据,这可能会导致意外结果。

rm -rf build *.egg-info

如果您不这样做,则预计不会正常工作。

现在这已经不成问题了。

  1. 如果您正在构建源代码分发版( sdist),那么您可以使用以下任何方法。

  2. 如果您正在构建一个轮子( bdist_wheel),则include_package_dataandMANIFEST.in将被忽略,您必须使用package_dataand data_files

INCLUDE_PACKAGE_DATA

这是一个不错的选择,但bdist_wheel不尊重它。

setup(
    ...
    include_package_data=True
)

# MANIFEST.in
include package/data.json

DATA_FILES 用于非包数据

这是最灵活的选项,因为您可以将存储库中的任何文件添加到sdistbdist_wheel

setup(
    ....
    data_files=[
        ('output_dir',['conf/data.json']),
    ]
    # For sdist, output_dir is ignored!
    #
    # For bdist_wheel, data.json from conf dir in root of your repo 
    # and stored at `output_dir/` inside of the sdist package.
)

PACKAGE_DATA 用于包内的非 python 文件

与上面类似,但是bdist_wheel让我们将数据文件放入包中。它是相同的,sdist但有更多的限制,data_files因为文件只能从你的包子目录中获取。

setup(
    ...
    package_data={'package':'data.json'},
    # data.json must be inside of your actual package
)
于 2018-03-26T22:03:11.490 回答
27

您可以使用package_dataand data_filesinsetup.py来指定其他文件,但它们很难正确(和错误)

另一种方法是使用MANIFEST.in并添加您的include_package_data=True,如此处所示setup()setup.py

使用此指令,MANIFEST.in将用于指定不仅要包含在源 tarball/zip 中的文件,还要包含在 wheel 和 win32 安装程序中。这也适用于任何 python 版本(我在从 py2.6 到 py3.6 的项目上进行了测试)。

2020 年更新:似乎 MANIFEST.in 在 Python 3 中不再受到轮子的尊重,尽管它仍然在 tar.gz 中,即使您设置了include_package_data=True.

以下是解决方法:您需要同时指定include_package_datapackages

如果您的 Python 模块位于“pymod”文件夹中,则以下是适当的设置:

setup( ...
    include_package_data = True,
    packages = ['pymod'],
)

如果您的 python 脚本位于根目录,请使用:

setup( ...
    include_package_data = True,
    packages = ['.'],
)

然后,您可以使用 7-zip 等 zip 存档软件打开您的 .whl 文件,以检查您想要的所有文件是否确实在其中。

于 2016-10-03T01:53:59.607 回答
11

您可以使用data_files指令指定要安装的额外文件。那是你要找的吗?这是一个小例子:

from setuptools import setup
from glob import glob

setup(
    name='extra',
    version='0.0.1',
    py_modules=['extra'],
    data_files=[
        ('images', glob('assets/*.png')),
    ],
)
于 2014-09-19T13:23:51.987 回答
4

include_package_data是要走的路,它适用于 sdist和 wheel

但是你必须做对,我花了几个月的时间才弄清楚这一点,所以这就是我学到的。

诀窍本质上是在选项名称中给出的include_PACKAGE_data数据文件需要位于包子文件夹中

当且仅当

  • include_package_data是真的
  • 数据文件列在MANIFEST.in(*另见我在最后关于的注释setuptools_scm
  • 并且数据文件位于包目录下

然后将包含数据文件。

工作示例:

鉴于该项目具有以下结构和文件:

|- MANIFEST.in
|- setup.cfg
|- setup.py
|
\---foo
    |- __init__.py
    |
    \---data
         - example.png

以及以下配置:

清单.in:

recursive-include foo/data *

安装程序.py

import setuptools

setuptools.setup()

设置.cfg

[metadata]
name = wheel-data-files-example
url = www.example.com
maintainer = None
maintainer_email = none@example.com

[options]
packages =
    foo
include_package_data = True

sdist 包和您构建的轮子也将包含example.png数据文件。

(当然,也可以直接在 setup.py 中指定配置而不是 setup.cfg。但这与示例无关。)

更新:对于 src 布局项目

这也适用于使用 src 布局的项目,如下所示:

|- MANIFEST.in
|- setup.cfg
|- setup.py
|
\---src
    |
    \---foo
        |- __init__.py
        |
        \---data
             - example.png

要使其正常工作,请使用以下命令告诉 setuptools 有关 src 目录的信息package_dir

设置.cfg

[metadata]
name = wheel-data-files-example
url = www.example.com
maintainer = None
maintainer_email = none@example.com

[options]
packages =
    foo
include_package_data = True
package_dir =
    =src

并在清单中调整路径:

清单.in:

recursive-include src/foo/data *

注意:如果您使用,则不需要 Manifest.insetuptools_scm

如果您碰巧使用了 setuptools 并添加了setuptools_scm插件(在 pypi 上),那么您不需要管理 Manifest.in 文件。相反, setuptools_scm 将负责将 git 跟踪的所有文件都添加到包中。

因此,对于这种情况,是否将文件添加到 sdist/wheel 的规则是:当且仅当

  • include_package_data是真的
  • 该文件由 git(或其他 setuptools_scm 支持的工具)跟踪
  • 并且数据文件位于包目录下

然后将包含数据文件。

于 2020-09-07T15:19:30.117 回答
0

我有 config/ 目录,其中包含 JSON 文件,我需要将其添加到 wheel 包中。因此,我已将这些行添加到MANIFEST.in

recursive-include config/ *.json

以下指令setup.py

setup(
 ...
 include_package_data=True,
)

没有任何效果。直到我创建了一个名为__init__.pyinsideconfig/目录的空文件。

(Python 3.6.7、wheel 3.6.7、setuptools 39.0.1)

于 2019-02-06T12:27:51.053 回答