问题:在setup.py中包含非Python文件
如何setup.py
包含不属于代码的文件?(具体来说,这是一个许可证文件,但也可以是其他任何东西。)
我希望能够控制文件的位置。在原始源文件夹中,该文件位于包的根目录中。(即与最上层处于同一级别__init__.py
。)我希望它在安装软件包时准确地保持在该位置,而与操作系统无关。我怎么做?
回答 0
可能最好的方法是使用setuptools
package_data
指令。这确实意味着要使用setuptools
(或distribute
)而不是distutils
,但这是一个非常无缝的“升级”。
这是完整(但未经测试)的示例:
from setuptools import setup, find_packages
setup(
name='your_project_name',
version='0.1',
description='A description.',
packages=find_packages(exclude=['ez_setup', 'tests', 'tests.*']),
package_data={'': ['license.txt']},
include_package_data=True,
install_requires=[],
)
请注意此处的关键行:
package_data={'': ['license.txt']},
include_package_data=True,
package_data
是dict
包名称(空=所有包)中的一组模式(可以包含glob)。例如,如果只想指定包中的文件,也可以这样做:
package_data={'yourpackage': ['*.txt', 'path/to/resources/*.txt']}
此处的解决方案绝对是不py
使用.py
扩展名重命名非文件。
有关更多信息,请参见Ian Bicking的演示文稿。
更新:另一种[更好]的方法
如果您只想控制源代码分发(sdist
)的内容并使文件位于软件包外部(例如,顶级目录),则另一种有效的方法是添加MANIFEST.in
文件。有关此文件的格式,请参见Python文档。
自编写此回复以来,我发现使用MANIFEST.in
通常是一种较为轻松的方法,只需确保您的源分发(tar.gz
)具有所需的文件即可。
例如,如果您要包括requirements.txt
来自顶层的目录,则递归包括顶层“数据”目录:
include requirements.txt
recursive-include data *
不过,为了在安装时将这些文件复制到site-packages内软件包的文件夹中,您需要提供include_package_data=True
此setup()
功能。有关更多信息,请参见添加非代码文件。
回答 1
要完成您要描述的内容,将需要两个步骤…
- 该文件需要添加到源tarball中
- 需要修改setup.py才能将数据文件安装到源路径
步骤1:要将文件添加到源tarball,请将其包括在MANIFEST中
在包含setup.py的文件夹中创建一个MANIFEST模板
清单基本上是一个文本文件,其中包含要在源tarball中包含的所有文件的列表。
这是我的项目清单如下所示:
- CHANGELOG.txt
- INSTALL.txt
- LICENSE.txt
- pypreprocessor.py
- README.txt
- setup.py
- test.py
- TODO.txt
注意:尽管sdist 确实会自动添加一些文件,但我更愿意明确指定它们以确保确定,而不是预测它会做什么和不做什么。
步骤2:要将数据文件安装到源文件夹,请修改setup.py
由于您要向源安装文件夹中添加数据文件(LICENSE.txt),因此需要修改数据安装路径以匹配源安装路径。这是必需的,因为默认情况下,数据文件与源文件的安装位置不同。
要修改数据安装目录以匹配源安装目录…
使用以下命令从distutils中获取安装目录信息:
from distutils.command.install import INSTALL_SCHEMES
修改数据安装目录以匹配源安装目录:
for scheme in INSTALL_SCHEMES.values():
scheme['data'] = scheme['purelib']
然后,将数据文件和位置添加到setup()中:
data_files=[('', ['LICENSE.txt'])]
注意:上面的步骤应该完全按照您所描述的标准方式完成,而无需任何扩展库。
回答 2
创建MANIFEST.in
在项目根与recursive-include
所需目录或include
使用的文件名。
include LICENSE
include README.rst
recursive-include package/static *
recursive-include package/templates *
回答 3
我想对其中一个问题发表评论,但我的声誉不足以做到这一点>。>
这是对我有用的东西(在参考文档后进行介绍):
package_data={
'mypkg': ['../*.txt']
},
include_package_data: False
奇怪的是,最后一行对我也很关键(您也可以忽略此关键字参数-原理相同)。
它的作用是将所有文本文件复制到顶级或根目录中(比mypkg
您要分发的包高一级)。
希望这可以帮助!
回答 4
步骤1:MANIFEST.in
使用setup.py在同一文件夹中创建文件
步骤2:包含要添加的文件的相对路径MANIFEST.in
include README.rst
include docs/*.txt
include funniest/data.json
第3步:设置include_package_data=True
在setup()
功能将这些文件复制到站点包
回答 5
现在是2019年,这是正在起作用的-尽管在这里和那里都提供了建议,但我在互联网上发现的中途记载的内容正在使用中setuptools_scm
,并作为选项传递给了setuptools.setup
。这将包括在VCS上版本化的所有数据文件(无论是git还是其他版本)到wheel软件包,并将从git存储库进行“ pip install”以将这些文件带到一起。
因此,我仅将这两行添加到“ setup.py”的设置调用中。无需额外安装或导入:
setup_requires=['setuptools_scm'],
include_package_data=True,
无需手动列出package_data或在MANIFEST.in文件中-如果已对其进行版本控制,则它将包含在软件包中。关于“ setuptools_scm”的文档着重于从提交位置创建版本号,而忽略了添加数据文件的真正重要部分。(如果我的中间滚轮文件名为“ * 0.2.2.dev45 + g3495a1f”,或者使用我输入的硬编码版本号“ 0.3.0dev0”,我就不会在意,但是将程序的关键文件留给后面的工作有些重要)
回答 6
在setup.py下的setup(:
setup(
name = 'foo library'
...
package_data={
'foolibrary.folderA': ['*'], # All files from folder A
'foolibrary.folderB': ['*.txt'] #All text files from folder B
},
回答 7
这是一个对我有用的简单答案。
首先,根据上述Python Dev的评论,不需要setuptools:
package_data is also available to pure distutils setup scripts
since 2.3. – Éric Araujo
太好了,因为在软件包上放置了setuptools要求,这意味着您还必须安装它。简而言之:
from distutils.core import setup
setup(
# ...snip...
packages = ['pkgname'],
package_data = {'pkgname': ['license.txt']},
)
回答 8
我只是想跟进我发现在Centos 6上使用Python 2.7的工作。如上所述,添加package_data或data_files对我不起作用。我添加了MANIFEST.IN以及我想要的文件,该文件将非python文件放到了tarball中,但没有通过RPM将它们安装在目标计算机上。
最后,我可以使用setup / setuptools中的“选项”将文件放入解决方案中。选项文件使您可以从setup.py修改规范文件的各个部分。如下。
from setuptools import setup
setup(
name='theProjectName',
version='1',
packages=['thePackage'],
url='',
license='',
author='me',
author_email='me@email.com',
description='',
options={'bdist_rpm': {'install_script': 'filewithinstallcommands'}},
)
档案-MANIFEST.in:
include license.txt
文件-filewithinstall命令:
mkdir -p $RPM_BUILD_ROOT/pathtoinstall/
#this line installs your python files
python setup.py install -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES
#install license.txt into /pathtoinstall folder
install -m 700 license.txt $RPM_BUILD_ROOT/pathtoinstall/
echo /pathtoinstall/license.txt >> INSTALLED_FILES
回答 9
找出解决方法:将我重命名lgpl2.1_license.txt
为lgpl2.1_license.txt.py
,并在文本周围加上了三引号。现在,我不需要使用该data_files
选项,也无需指定任何绝对路径。我知道将其制作为Python模块很丑陋,但我认为它比指定绝对路径丑陋得多。