MANIFEST.in在“ python setup.py install”上被忽略-没有安装数据文件?


89

这是我精简后的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'],
)

MANIFEST.in:

include *.txt
include whyteboard-help/*.*
recursive-include locale *.mo
recursive-include images *.png

当我运行“ python setup.py install sdist”时,我得到一个带有“ whyteboard-0.41”根文件夹的不错的.tar.gz,其中包含我的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文件中生成的目录结构相同的目录结构,因为这是我的程序希望查找其资源的方式。

如何获得“安装”以创建此目录结构?据我所知,它似乎无视我的清单文件。


Answers:


30

除了Ned的答案(这是核心问题)之外,还有一些注意事项:

Distutils不会在site-packages(或dist-packages在Debian / Ubuntu上)的每个项目子目录中安装Python软件包和模块:site-packages如您所见,它们直接安装在中。因此,whyteboard-xxsdist中的包含目录将不会以最终安装的形式存在。

这意味着您应该谨慎地命名您的名称data_files,以阐明它们属于哪个项目,因为这些文件/目录直接安装在全局site-packages目录中,而不是在任何包含whyteboard目录中。

或者你可以反而让你的数据package_data中的whyteboard包(这意味着它需要生活里面那个包,即旁__init__.py),然后这不是一个问题。

最后,同时包含whyteboard.py模块py_moduleswhyteboard/__init__.py包并没有多大意义packages。两者是互斥的,并且如果两者都使用,则whyteboard.py导入将忽略该模块,而使用相同名称的软件包。

如果whyteboard.py只是一个脚本,并且不打算导入,则应使用脚本选项,并将其从中删除py_modules


1
那真不幸。我不喜欢拥有包数据的想法-对我来说,那些资源位于源目录之外更有意义。我也不喜欢必须以程序名称作为前缀的目录名称(即使我已经为帮助文件添加了名称)。嗯..
史蒂文斯普罗特

67

MANIFEST.in告诉Distutils源分发中要包含哪些文件,但这不会直接影响安装的文件。为此,您需要在文件中包括适当的setup.py文件,通常将其作为打包数据或作为其他文件


我尝试添加软件包数据列表,但未使用我指定的文件。我不确定文件的位置是否相对于软件包的整体安装而言。无论如何,它仍然没有按照我期望的正确目录结构写入文件。
史蒂文·斯普罗亚特

此答案中链接的文档为您提供了有关data_files和package_data的安装位置的所有信息。如果这些选项都不适合您,请使用您尝试使用的确切语法,结果以及期望的内容来更新您的问题。
卡尔·迈耶

4
这对我有用:在setup.py的data_packages内部复制MANIFEST.in条目使一切正常。谢谢Ned-多年来,我一直无法理解这一点。希望现在我的distutils / setuptools / distribute经验会更有意义。
乔纳森·哈特利

7
能够在无法安装的程序包中包含文件的这种设计是否有意义?什么时候使用?
罗杰·达尔2014年

27

我不知道为什么我的MANIFEST.in文件在运行时会被忽略python setup.py install-事实证明include_package_data=True解决了这个问题。该package_data选项实际上不是必需的。


很好,为什么include_package_data=True没有默认值?
liang

8

在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") ...

并安装了这些树中的所有内容。


11
很好,但是要安装到哪里?对我而言,使用“ pip install”时,我的data_files进入我的virtualenv的根目录(即,由所有virtualenv软件包共享的单个目录。)如果使用“ setup.py install”,则我的data_files进入“ site-包/<mypackage>.egg/”。如果文件是运行时所需的数据,那么对于我的代码而言,找到这些文件绝非易事,当然,我必须在运行时搜索两个目录。如果这些文件是我的LICENSE文件,那么对于从我的源到LICENSE的用户而言,这两种情况都不是小事。困惑。
乔纳森·哈特利

8

您应该使用setuptools:

#!/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文件来完成工作,而是包括所有需要的文件。


这确实对我有用setuptools。我构建了Debian软件包,并且看到package_data字典中列出的林间空地文件仅在添加后才出现在正确的位置include_package_data=Tru
mlt

3

最小的已发布可运行示例

关键要点:仅对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-with-data

#!/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

setup.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'],
)

参考书目:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.