我在遇到同样的问题时发现了这篇文章。
我的经验与其他答案中的经验相矛盾。
include_package_data=True 确实将数据包含在
bdist!setuptools中的解释
documentation
缺乏上下文和故障排除提示,但
include_package_data 按广告宣传。
我的设置:
- Windows / Cygwin
- git 版本 2.21.0
- Python 3.8.1 Windows 分发版
-
setuptoolsv47.3.1
-
check-manifestv0.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() 没有找到它。
一个经常被引用但不正确的解决方案是将一个空的
_my_data 文件夹中的__init__.py 文件。
这确实使它成为一个包,所以它确实包含文件夹
_my_data 在分发中。但是里面的数据文件
_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 不是一个有效的测试
注意:pip install -e . 不显示数据文件是否
包含在bdist中。
符号链接使安装的行为就像
包括数据文件(因为它们已经存在于本地
开发者的计算机)。
pip install my_package之后,数据文件在
虚拟环境的lib/site-packages/my_package/ 文件夹,
使用与上面列表中显示的完全相同的文件结构
whl 的内容。
发布到 TestPyPI 是一种缓慢的测试方式
发布到 TestPyPI,然后安装并查看
lib/site-packages/my_packages 是一个有效的测试,但它也是
耗时。