如何使用 setuptools *安装* 额外的包数据?

How to *install* extra package data using setuptools?

这看起来很像 this question,但又不完全是。

该问题的答案包括如何将额外数据获取到源代码分发和二进制分发中,但实际上并未解决如何获取包数据 installed源代码分发,或如何将它们安装在 wheel 文件中。

这是我的意思的一个例子 (python 3.7.4):

% ls
MANIFEST.in README.txt  foopackage  setup.py    venv

% cat setup.py
# -*- coding: utf-8 -*-

from setuptools import setup, find_packages

setup(
    name='foopackage',
    version='0.0.1',
    description='A Package Full of Foo',
    packages=find_packages(),
    package_data={
        'foopackage': [
            'README.txt',
        ],
    },
    include_package_data=True,
)

% cat MANIFEST.in
include README.txt

% . venv/bin/activate
(venv)
% python setup.py sdist bdist_wheel
[...]
% ls dist
foopackage-0.0.1-py3-none-any.whl foopackage-0.0.1.tar.gz
(venv)
% unzip -v dist/foopackage-0.0.1-py3-none-any.whl| grep README.txt
(venv)
% tar tvzf dist/foopackage-0.0.1.tar.gz| grep README.txt
-rw-r--r--  0 matt   staff       0  8 Nov 17:21 foopackage-0.0.1/README.txt
(venv)
% deactivate

% cd ../foo

% . py/bin/activate
(py)
% pip install ../foopackage/dist/foopackage-0.0.1.tar.gz
Processing ../foopackage/dist/foopackage-0.0.1.tar.gz
Installing collected packages: foopackage
  Found existing installation: foopackage 0.0.1
    Uninstalling foopackage-0.0.1:
      Successfully uninstalled foopackage-0.0.1
  Running setup.py install for foopackage ... done
Successfully installed foopackage-0.0.1
You are using pip version 19.0.3, however version 19.3.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(py)
% find . -name README.txt
(py)
%

README.txt 文件未包含在 wheel 中,尽管包含在 sdist 文件中,但在安装该软件包时并未安装。

我似乎找不到让 setuptools 在某处实际安装此文件的魔法咒语。我错过了什么?

我可能应该指出,我正在构建的真实包必须与 py27 和 py34+ 兼容,以防以任何方式限制解决方案。

问题在

package_data={
    'foopackage': [
        'README.txt',
    ],
},

使用此代码,您可以声明您的 foopackage 包含一个文件 README.txtpackage_data 中的文件模式相对于它们所属的包进行处理)。但事实并非如此!该文件位于根文件夹中,而不是 foopackage/ 子文件夹中。这也是该文件未包含在您的车轮中的原因。

通过在 MANIFEST.in 中列出文件,您强制 setuptools 将该文件包含到源 dist 中,但 setuptools 不知道如何处理该文件 — 它需要该文件进入 foopackage/.

有 2 种方法可以解决此问题。 1,你可以声明文件的相对路径:

package_data={
    'foopackage': [
        '../README.txt',
    ],
},

在这种情况下,填充将安装在 foopackage/../README.txt,即 site-packages/ 目录中。这可能是你想要的。

还是不行。在这种情况下,正确的解决方案是将文件移动到 foopackage/、修复 MANIFEST.in 并重建 sdist 和 wheel(s)。