MANIFEST.in 在“python setup.py install”上被忽略-没有安装数据文件?
- 2025-03-19 08:56:00
- admin 原创
- 11
问题描述:
下面是我的精简版 setup.py 脚本,其中删除了非代码部分:
#!/usr/bin/env python
from distutils.core import setup
from whyteboard.misc import meta
setup(
name = 'Whyteboard',
version = meta.version,
packages = ['whyteboard', 'whyteboard.gui', 'whyteboard.lib', 'whyteboard.lib.pubsub',
'whyteboard.lib.pubsub.core', 'whyteboard.lib.pubsub.utils', 'whyteboard.misc'],
py_modules = ['whyteboard'],
scripts = ['whyteboard.py'],
)
清单.在:
include *.txt
include whyteboard-help/*.*
recursive-include locale *.mo
recursive-include images *.png
当我运行“python setup.py install sdist”时,我得到了一个漂亮的 .tar.gz,其中有一个“whyteboard-0.41”根文件夹,里面有我的 locale/images/ 和 whyteboard-help/ 文件夹。这里面还有我的 whyteboard.py 脚本,它可以从 whyteboard 源包内部启动我的程序。
所以:
whyteboard/
├── locale/
├── images
├── whyteboard-help/
├── whyteboard/
│ ├── __init__.py
│ └── other packages etc
├── whyteboard.py
├── README
├── setup.py
└── CHANGELOG
这反映了我的程序的源代码,一切都应该是这样的,而且是正确的。
但是当我运行“python setup.py install”时,我的任何数据文件都没有被写入 - 只有“whyteboard”源包,并且 whyteboard.py 放在 /usr/local/lib/python2.6/dist-packages/ 中。
理想情况下,我希望在 dist-packages 中创建与 .tar.gz 文件中生成的目录结构相同的目录结构,因为这是我的程序期望查找其资源的方式。
我如何让“安装”创建此目录结构?据我所知,它似乎忽略了我的清单文件。
解决方案 1:
MANIFEST.in
告诉 Distutils 源代码分发中应包含哪些文件,但这并不直接影响要安装哪些文件。为此,您需要在setup.py
文件中包含相应的文件,通常是作为包数据或附加文件。
解决方案 2:
我不明白为什么MANIFEST.in
运行时我的文件被忽略了python setup.py install
- 结果include_package_data=True
解决了这个问题。该package_data
选项实际上不是必需的。
解决方案 3:
除了 Ned 的回答(触及核心问题)之外,还有一些注释:
site-packages
Distutils 不会在(或Debian/Ubuntu 上)每个项目的子目录中安装 Python 包和模块dist-packages
:它们直接安装到 中site-packages
,如您所见。因此,whyteboard-xx
sdist 中包含的目录不会存在于最终安装形式中。
这意味着您应该小心地命名,data_files
以明确它们属于哪个项目,因为这些文件/目录直接安装到全局site-packages
目录中,而不是任何包含whyteboard
目录中。
或者您可以将数据制作成包package_data
中的数据whyteboard
(这意味着它需要位于该包内,即旁边__init__.py
),那么这就不是问题了。
whyteboard.py
最后,在 中同时拥有模块py_modules
和whyteboard/__init__.py
包是没有意义的packages
。这两者是互斥的,如果同时拥有这两个包,whyteboard.py
导入时会忽略该模块,而使用同名的包。
如果whyteboard.py
只是一个脚本,并且不打算导入,那么您应该使用脚本选项,并将其从中删除py_modules
。
解决方案 4:
您应该使用安装工具:
#!/usr/bin/env python
from setuptools import setup, find_packages
from whyteboard.misc import meta
setup(
name = 'Whyteboard',
version = meta.version,
packages = find_packages(),
include_package_data=True,
py_modules = ['whyteboard'],
scripts = ['whyteboard.py'],
)
这实际上并不是使用 MANIFEST 文件来完成工作,但它包含了所有需要的文件。
解决方案 5:
在 Mac OSX 上运行 python 2.6.1,除了使用 setup.py 中的data_files参数外,我完全没有运气。所有带有 MANIFEST.in 的操作都只会导致文件包含在 dist 包中,但从未安装。我检查了一些其他包,它们确实使用 data_files 来指定其他文件。
我创建了一个简短的函数来帮助枚举目录树中的所有文件
(target_dir, [文件列表]) data_files 期望的格式:
def gen_data_files(*dirs):
results = []
for src_dir in dirs:
for root,dirs,files in os.walk(src_dir):
results.append((root, map(lambda f:root + "/" + f, files)))
return results
现在我可以在我的设置调用中调用它:
setup(... data_files = gen_data_files("docs", "lib") ...
这些树中的所有内容都已安装。
解决方案 6:
最小已发布可运行示例
关键要点:只MANIFEST.in
对我有用,package_data
没有用。
在 Ubuntu 19.10、Python 3.7.5、wheel==0.32.3、setuptools==41.1.0、twine==3.1.1 上进行了测试。
最终用户如何使用来自https://pypi.org/project/python-sample-package-with-data/的包:
python3 -m pip install --user python-sample-package-with-data
python-sample-package-with-data
预期输出:
hello data
维护者如何发布它:
# One time setup.
python3 -m pip install --user setuptools wheel twine
# Every time you want to publish.
python setup.py sdist bdist_wheel
twine upload dist/*
rm -rf build dist *.egg-info
实际文件:
清单
# Or else pip install cannot find README.md on the setup.py under certain conditions.
include README.md
# This actually adds the data file.
include python_sample_package_with_data/mydata.txt
带有数据的 python-sample-package
#!/usr/bin/env python3
import python_sample_package_with_data
print(python_sample_package_with_data.get_data(), end='')
python_sample_package_with_data/__init__.py
try:
import importlib.resources as importlib_resources
except ImportError:
# In PY<3.7 fall-back to backported `importlib_resources`.
import importlib_resources
def get_data():
return importlib_resources.read_text(__name__, 'mydata.txt')
python_sample_package_with_data/mydata.txt
hello data
设置.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from setuptools import setup, find_packages
from os import path
this_directory = path.abspath(path.dirname(__file__))
with open(path.join(this_directory, 'README.md')) as f:
long_description = f.read()
setup(
name='python-sample-package-with-data',
version='0.0.3',
description='My short description',
long_description=long_description,
long_description_content_type='text/markdown',
url='https://github.com/cirosantilli/python-sample-package-with-data',
author='Ciro Santilli',
author_email='ciro.santilli.contact@gmail.com',
packages=find_packages(),
include_package_data=True,
scripts=['python-sample-package-with-data'],
)
参考书目:
如何正确分发带有数据文件的 pip 包?
Python pkg_resources 和包中的文件访问
在 Python 模块分发中查找文件
有任何 Python 函数可以获取“data_files”根目录吗?
MANIFEST.in、package_data 和 data_files 说明?
setup.py 没有安装数据文件