Python 如何向轮子添加其他文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24347450/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 04:27:40  来源:igfitidea点击:

How do you add additional files to a wheel?

pythonpippython-wheel

提问by jwhitlock

How do control what files are included in a wheel? It appears MANIFEST.inisn't used by python setup.py bdist_wheel.

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

UPDATE:

更新

I was wrong about the difference between installing from a source tarball vs a wheel. The source distribution includes files specified in MANIFEST.in, but the installed package only has python files. Steps are needed to identify additional files that should be installed, whether the install is via source distribution, egg, or wheel. Namely, package_datais needed for additional package files, and data_filesfor files outside your package like command line scripts or system config files.

我错了从源 tarball 安装与从轮子安装之间的区别。源代码分发包括 中指定的文件MANIFEST.in,但安装的包只有 python 文件。需要采取步骤来确定应该安装的其他文件,无论安装是通过源代码分发、egg 还是轮子安装。也就是说,额外的包文件需要package_data,包外的文件需要data_files,比如命令行脚本或系统配置文件。

Original Question

原始问题

I have a projectwhere I've been using python setup.py sdistto build my package, MANIFEST.into control the files included and excluded, and pyromaand check-manifestto confirm my settings.

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

I recently converted it to dual Python 2 / 3 code, and added a setup.cfg with

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

[bdist_wheel]
universal = 1

I can build a wheel with python setup.py bdist_wheel, and it appears to be a universal wheel as desired. However, it doesn't include all of the files specified in MANIFEST.in.

我可以用 建造一个轮子python setup.py bdist_wheel,它看起来是一个需要的万能轮。但是,它不包括MANIFEST.in.

What gets installed?

安装什么?

I dug deeper, and now know more about packaging and wheel. Here's what I learned:

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

I upload two package files to the multigtfs project on PyPi:

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

  • multigtfs-0.4.2.tar.gz- the source tar ball, which includes all the files in MANIFEST.in.
  • multigtfs-0.4.2-py2.py3-none-any.whl- The binary distribution in question.
  • multigtfs-0.4.2.tar.gz- 源 tar ball,其中包括MANIFEST.in.
  • multigtfs-0.4.2-py2.py3-none-any.whl- 有问题的二进制分布。

I created two new virtual environments, both with Python 2.7.5, and installed each package (pip install multigtfs-0.4.2.tar.gz). The two environments are almost identical. They have different .pycfiles, which are the "compiled" Python files. There are log files which record the different paths on disk. The install from the source tar ball includes a folder multigtfs-0.4.2-py27.egg-info, detailing the installation, and the wheel install has a multigtfs-0.4.2.dist-infofolder, with the details of that process. However, from the point of view of code using the multigtfs project, there is no difference between the two installation methods.

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

Explicitly, neither has the .zip files used by my test, so the test suite will fail:

明确地,我的测试中也没有使用 .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'

Specifying additional files

指定附加文件

Using the suggestions from the answers, I added some additional directives to setup.py:

使用答案中的建议,我添加了一些额外的指令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,
    ...
)

This installs the zip files (as well as the README) to the folder, and tests now run correctly. Thanks for the suggestions!

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

采纳答案by vgel

Have you tried using package_datain your setup.py? MANIFEST.inseems targetted for python versions <= 2.6, I'm not sure if higher versions even look at it.

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

After exploring https://github.com/pypa/sampleproject, their MANIFEST.insays:

在探索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

which seems to imply this method is outdated. Meanwhile, in setup.pythey declare:

这似乎意味着这种方法已经过时了。同时,在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.
    package_data={
        'sample': ['package_data.dat'],
    },
    ...
)

(I'm not sure why they chose a wildcard in MANIFEST.inand a filename in setup.py. They refer to the same file)

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

Which, along with being simpler, again seems to imply that the package_dataroute is superior to the MANIFEST.inmethod. Well, unless you have to support 2.6 that is, in which case my prayers go out to you.

其中,除了更简单之外,似乎再次暗示该package_data路线优于该MANIFEST.in方法。好吧,除非您必须支持 2.6,也就是说,在这种情况下,我向您祈祷。

回答by lazy1

You can specify extra files to install using the data_filesdirective. Is that what you're looking for? Here's a small example:

您可以使用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')),
    ],
)

回答by snapshoe

"A wheel is a ZIP-format archive ..." (http://wheel.readthedocs.org/en/latest)

“车轮是 ZIP 格式的存档……”(http://wheel.readthedocs.org/en/latest

So, treat the .whl file just like a .zip file. Add a file with:

因此,将 .whl 文件视为 .zip 文件。添加一个文件:

  • Python ZipFileobject
  • any archive/zip file utility, like 7-zip, Winzip, Ark, file-roller, etc.
  • Python ZipFile对象
  • 任何存档/zip 文件实用程序,如 7-zip、Winzip、Ark、file-roller 等。

回答by gaborous

You can use package_dataand data_filesin setup.pyto specify additional files, but they are ridiculously hard to get right (and buggy).

您可以使用package_datadata_filesinsetup.py来指定其他文件,但它们很难正确(并且有问题)

An alternative is to use MANIFEST.inand add include_package_data=Truein setup()of your setup.pyas indicated here.

另一种方法是使用MANIFEST.in和添加include_package_data=Truesetup()setup.py这里表示

With this directive, the MANIFEST.inwill be used to specify the files to include not only in source tarball/zip, but also in wheel and win32 installer. This also works with any python version (i tested on a project from py2.6 to py3.6).

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

UPDATE 2020: it seems the MANIFEST.in is not honored anymore by the wheel in Python 3, although it still is in the tar.gz, even if you set include_package_data=True.

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

Here is how to fix that: you need to specify both include_package_dataand packages.

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

If your Python module is inside a folder "pymod", here's the adequate setup:

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

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

If your python scripts are at the root, use:

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

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

Then you can open your .whl file with a zip archival software such as 7-zip to check that all the files you want are indeed inside.

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

回答by cmcginty

Before you make any changesin MANIFEST.inor setup.pyyou must remove old output directories. Setuptools is caching some of the data and this can lead to unexpected results.

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

rm -rf build *.egg-info

If you don't do this, expect nothing to work correctly.

如果您不这样做,请不要指望任何东西都能正常工作。

Now that is out of the way.

现在这已经不在了。

  1. If you are building a source distribution(sdist) then you can use any method below.

  2. If you are building a wheel(bdist_wheel), then include_package_dataand MANIFEST.inare ignored and you must use package_dataand data_files.

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

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

INCLUDE_PACKAGE_DATA

INCLUDE_PACKAGE_DATA

This is a good option, but bdist_wheeldoes not honor it.

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

setup(
    ...
    include_package_data=True
)

# MANIFEST.in
include package/data.json

DATA_FILES for non-package data

DATA_FILES 用于非包数据

This is most flexible option because you can add any file from your repo to a sdistor bdist_wheel

这是最灵活的选项,因为您可以将存储库中的任何文件添加到一个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 for non-python files inside of the package

PACKAGE_DATA 用于包内的非 python 文件

Similar to above, but for a bdist_wheellet's you put your data files inside of the package. It is identical for sdistbut has more limitations than data_filesbecause files can only source from your package subdir.

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

setup(
    ...
    package_data={'package':'data.json'},
    # data.json must be inside of your actual package
)

回答by Michael Spector

I had config/ directory with JSON files in it, which I needed to add to the wheel package. So, I've added these lines to MANIFEST.in:

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

recursive-include config/ *.json

The following directive to setup.py:

以下指令用于setup.py

setup(
 ...
 include_package_data=True,
)

And nothing worked. Until I've created an empty file called __init__.pyinside config/directory.

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

(Python 3.6.7, wheel 3.6.7, setuptools 39.0.1)

(Python 3.6.7,轮子 3.6.7,设置工具 39.0.1)