使用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/
是数据文件的位置。
答案 0 :(得分:234)
我意识到这是一个老问题......但是对于那些通过Google找到方法的人来说:package_data
是一个低调的dirty lie。它仅在构建二进制包(python setup.py bdist ...
)时使用,但在构建源包(python setup.py sdist ...
)时不。当然,这是荒谬的 - 人们会期望构建源代码分发会导致一组文件可以发送给其他人来构建二进制分发。
在任何情况下,使用MANIFEST.in
对于二进制和源代码分发都将 。
答案 1 :(得分:25)
我刚才有同样的问题。解决方案只是删除include_package_data=True
。
在reading here之后,我意识到include_package_data
的目的是包含来自版本控制的文件,而不是像名称所暗示的那样仅包含“包数据”。来自文档:
[include_package_data]的数据文件必须在CVS或Subversion控件
下...
如果您希望对包含的文件进行更精细的控制(例如,如果 您在包目录中有文档文件,并希望排除 它们来自安装),然后您还可以使用
package_data
关键字。
把这个论点修正了,这恰巧是为什么当你切换到distutils时它也起作用,因为它没有采用这个论点。
答案 2 :(得分:16)
遵循@Joe的建议删除include_package_data=True
行也对我有用。
为了详细说明,我有没有 MANIFEST.in
文件。我使用Git而不是CVS。
Repository采用这种形式:
/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
。
答案 3 :(得分:11)
include_package_data=True
为我工作。
如果你使用git,请记得在setuptools-git
中加入install_requires
。比Manifest
或包含package_data
中的所有路径(在我的情况下它是一个带有各种静力学的django应用程序)更为无聊
(粘贴我发表的评论,正如k3-rnc提到的那样,实际上是有帮助的)
答案 4 :(得分:5)
更新:此答案已过时且信息不再有效。所有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'],
},
)
答案 5 :(得分:4)
古老的问题然而......蟒蛇的包管理真的还有很多不足之处。所以我有一个使用pip本地安装到指定目录的用例,并且很惊讶package_data和data_files路径都没有用。我并不热衷于在repo中添加另一个文件,所以我最终利用了data_files和setup.py选项--install-data;像这样的东西
pip install . --install-option="--install-data=$PWD/package" -t package
答案 6 :(得分:3)
只需删除行:
include_package_data=True,
从您的安装脚本,它将正常工作。 (刚刚通过最新的设置工具进行了测试。)
答案 7 :(得分:2)
从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()
有关更多信息,请参见configuring setup using setup.cfg files。
some talk of deprecating setup.cfg
中有PEP 518赞成pyproject.toml
,但从2020年2月21日起这仍然是临时的。
答案 8 :(得分:2)
我发现这个帖子时遇到了同样的问题。
我的经验与其他答案中的经验相反。
include_package_data=True
是否将数据包括在
bdist! setuptools
中的解释
documentation
缺少上下文和故障排除技巧,但是
include_package_data
如广告所宣传。
我的设置:
setuptools
v47.3.1 check-manifest
v0.42 这是我的操作指南。
这是我在PyPI上发布的项目的文件结构。
(它将应用程序安装在__main__.py
中。)
├── LICENSE.md
├── MANIFEST.in
├── my_package
│ ├── __init__.py
│ ├── __main__.py
│ └── _my_data <---- folder with data
│ ├── consola.ttf <---- data file
│ └── icon.png <---- data file
├── README.md
└── setup.py
此处是setuptools.setup()
中通用的起点
setup.py
。
setuptools.setup(
...
packages=setuptools.find_packages(),
...
)
setuptools.find_packages()
将我所有的软件包都包含在
分配。我唯一的包裹是my_package
。
包含我的数据_my_data
的子文件夹不被视为
由Python打包,因为它不包含__init__.py
,
因此find_packages()
找不到它。
一种经常被引用但又不正确的解决方案是将一个空白
__init__.py
文件夹中的_my_data
文件。
此做使其成为一个包,因此它做包含文件夹
_my_data
。但是里面的数据文件
{strong>不包含_my_data
。
因此将_my_data
打包成一个包没有帮助。
解决方案是:
sdist
已包含数据文件include_package_data=True
以将数据文件也包含在bdist
中可以通过三个步骤来进行可重复的实验:
$ rm -fr build/ dist/ my_package.egg-info/
$ check-manifest
$ python setup.py sdist bdist_wheel
我将逐步细分这些内容:
$ rm -fr build/ dist/ my_package.egg-info/
check-manifest
,确保MANIFEST.in
与相匹配
版本控制下文件的Git索引:$ check-manifest
如果MANIFEST.in
还不存在,请从Git 创建
版本控制下的文件索引:
$ check-manifest --create
以下是创建的MANIFEST.in
:
include *.md
recursive-include my_package *.png
recursive-include my_package *.ttf
没有理由手动编辑此文件。
只要应该受版本控制的所有内容
在版本控制下(即是Git索引的 part ),
check-manifest --create
做正确的事。
注意:如果文件属于以下两种情况,则它们都不属于Git索引:
.gitignore
中被忽略.git/info/exclude
如果任何文件受版本控制,则不应
在版本控制下,check-manifest
发出警告,
指定建议从Git索引中删除哪些文件。
$ python setup.py sdist bdist_wheel
现在检查sdist
(源分发)和bdist_wheel
(内部版本)以查看它们是否包含数据文件。
查看sdist
的内容(只有相关行是
如下所示):
$ tar --list -f dist/my_package-0.0.1a6.tar.gz
my_package-0.0.1a6/
...
my_package-0.0.1a6/my_package/__init__.py
my_package-0.0.1a6/my_package/__main__.py
my_package-0.0.1a6/my_package/_my_data/
my_package-0.0.1a6/my_package/_my_data/consola.ttf <-- yay!
my_package-0.0.1a6/my_package/_my_data/icon.png <-- yay!
...
因此sdist
已包含数据文件,因为它们是
在MANIFEST.in
中列出。没有其他可做的事情了
sdist
中的数据文件。
查看bdist
的内容(它是一个.zip文件,已解析
与zipfile.ZipFile
):
$ python check-whl.py
my_package/__init__.py
my_package/__main__.py
my_package-0.0.1a6.dist-info/LICENSE.md
my_package-0.0.1a6.dist-info/METADATA
my_package-0.0.1a6.dist-info/WHEEL
my_package-0.0.1a6.dist-info/entry_points.txt
my_package-0.0.1a6.dist-info/top_level.txt
my_package-0.0.1a6.dist-info/RECORD
注意:您需要创建自己的check-whl.py
脚本来生成
以上输出。只有三行:
from zipfile import ZipFile
path = "dist/my_package-0.0.1a6-py3-none-any.whl" # <-- CHANGE
print('\n'.join(ZipFile(path).namelist()))
正如预期的那样,bdist
缺少数据文件。
_my_data
文件夹完全丢失。
如果我创建_my_data/__init__.py
怎么办?我重复
实验之后,我发现数据文件仍然不存在!
_my_data/
文件夹已包含,但其中不包含数据
文件!
与其他人的经历相反,这是的工作:
setuptools.setup(
...
packages=setuptools.find_packages(),
include_package_data=True, # <-- adds data files to bdist
...
)
修复后,重做实验:
$ rm -fr build/ dist/ my_package.egg-info/
$ check-manifest
$ python.exe setup.py sdist bdist_wheel
确保sdist
仍具有数据文件:
$ tar --list -f dist/my_package-0.0.1a6.tar.gz
my_package-0.0.1a6/
...
my_package-0.0.1a6/my_package/__init__.py
my_package-0.0.1a6/my_package/__main__.py
my_package-0.0.1a6/my_package/_my_data/
my_package-0.0.1a6/my_package/_my_data/consola.ttf <-- yay!
my_package-0.0.1a6/my_package/_my_data/icon.png <-- yay!
...
查看bdist
的内容:
$ python check-whl.py
my_package/__init__.py
my_package/__main__.py
my_package/_my_data/consola.ttf <--- yay!
my_package/_my_data/icon.png <--- yay!
my_package-0.0.1a6.dist-info/LICENSE.md
my_package-0.0.1a6.dist-info/METADATA
my_package-0.0.1a6.dist-info/WHEEL
my_package-0.0.1a6.dist-info/entry_points.txt
my_package-0.0.1a6.dist-info/top_level.txt
my_package-0.0.1a6.dist-info/RECORD
我建议使用概述的方法进行故障排除/测试
检查sdist
和bdist
。
注意:pip install -e .
不会显示是否存在数据文件
包含在bdist
中。
符号链接使安装行为类似于 包含数据文件(因为它们已经存在于本地 开发人员的计算机)。
pip install my_package
之后,数据文件位于
虚拟环境的lib/site-packages/my_package/
文件夹,
使用上面列表中显示的完全相同的文件结构
whl
的内容。
发布到TestPyPI,然后安装并查看
lib/site-packages/my_packages
是有效的测试,但也是
费时的。
答案 9 :(得分:1)
将包含数据包数据的文件夹移到模块文件夹中解决了我的问题。
请参阅此问题:MANIFEST.in ignored on "python setup.py install" - no data files installed?
答案 10 :(得分:1)
这两天我遇到了同样的问题,但是即使这个线程对我来说也不清楚。一切都令人困惑。因此,我进行了研究并找到了解决方案。基本上在这种情况下,这就是您应该做的:
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'],
},
)
答案 11 :(得分:0)
对于像这样的目录结构:
foo/
├── foo
│ ├── __init__.py
│ ├── a.py
│ └── data.txt
└── setup.py
和setup.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from setuptools import setup
NAME = 'foo'
DESCRIPTION = 'Test library to check how setuptools works'
URL = 'https://none.com'
EMAIL = 'gzorp@bzorp.com'
AUTHOR = 'KT'
REQUIRES_PYTHON = '>=3.6.0'
setup(
name=NAME,
version='0.0.0',
description=DESCRIPTION,
author=AUTHOR,
author_email=EMAIL,
python_requires=REQUIRES_PYTHON,
url=URL,
license='MIT',
classifiers=[
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
],
packages=['foo'],
package_data={'foo': ['data.txt']},
include_package_data=True,
install_requires=[],
extras_require={},
cmdclass={},
)
python setup.py bdist_wheel
有效。
答案 12 :(得分:0)
像这个帖子中的其他人一样,我对长寿和仍然缺乏清晰度的组合感到有点惊讶,但对我来说最好的答案是使用 check-manifest
作为在@mike-gazes 的回答中推荐
因此,仅使用 setup.cfg
而没有 setup.py
以及包中所需的其他文本和 python 文件,对我有用的是将其保留在 setup.cfg 中:
[options]
packages = find:
include_package_data = true
并根据 MANIFEST.in
输出更新 check-manifest
:
include *.in
include *.txt
include *.yml
include LICENSE
include tox.ini
recursive-include mypkg *.py
recursive-include mypkg *.txt