我如何使setup.py包含一个不是代码一部分的文件?(具体来说,它是一个许可证文件,但也可以是其他任何东西。)

我希望能够控制文件的位置。在原始源文件夹中,文件位于包的根目录中。(即与最顶层的__init__.py在同一层。)我希望它在安装包时保持在那里,而不管操作系统是什么。我怎么做呢?


当前回答

以上这些方法对我都不起作用。是这个回答救了我。 显然,为了在安装期间提取这些数据文件,我必须做几件事:

Like already mentioned - Add a MANIFEST.in to the project and specify the folder/files you want to be included. In my case: recursive-include folder_with_extra_stuff * Again, like already mentioned - Add include_package_data=True to your setup.py. This is crucial, because without it only the files that match *.py will be brought. This is what was missing! - Add an empty __init__.py to your data folder. For me I had to add this file to my folder-with-extra-stuff. Extra - Not sure if this is a requirement, but with my own python modules I saw that they're zipped inside the .egg file in site-packages. So I had to add zip_safe=False to my setup.py file.

最终目录结构

my-app/
├─ app/
│  ├─ __init__.py
│  ├─ __main__.py
├─ folder-with-extra-stuff/
│  ├─ __init__.py
│  ├─ data_file.json
├─ setup.py
├─ MANIFEST.in

其他回答

以上这些方法对我都不起作用。是这个回答救了我。 显然,为了在安装期间提取这些数据文件,我必须做几件事:

Like already mentioned - Add a MANIFEST.in to the project and specify the folder/files you want to be included. In my case: recursive-include folder_with_extra_stuff * Again, like already mentioned - Add include_package_data=True to your setup.py. This is crucial, because without it only the files that match *.py will be brought. This is what was missing! - Add an empty __init__.py to your data folder. For me I had to add this file to my folder-with-extra-stuff. Extra - Not sure if this is a requirement, but with my own python modules I saw that they're zipped inside the .egg file in site-packages. So I had to add zip_safe=False to my setup.py file.

最终目录结构

my-app/
├─ app/
│  ├─ __init__.py
│  ├─ __main__.py
├─ folder-with-extra-stuff/
│  ├─ __init__.py
│  ├─ data_file.json
├─ setup.py
├─ MANIFEST.in

没有一个答案对我有用,因为我的文件在顶层,在包之外。我使用了自定义构建命令。

import os
import setuptools
from setuptools.command.build_py import build_py
from shutil import copyfile

HERE = os.path.abspath(os.path.dirname(__file__))
NAME = "thepackage"

class BuildCommand(build_py):
    def run(self):
        build_py.run(self)

        if not self.dry_run:
            target_dir = os.path.join(self.build_lib, NAME)
            for fn in ["VERSION", "LICENSE.txt"]:
                copyfile(os.path.join(HERE, fn), os.path.join(target_dir,fn))

 
 
setuptools.setup(
    name=NAME,
    cmdclass={"build_py": BuildCommand},
    description=DESCRIPTION,
    ...
)

这在2020年有效!

正如其他人所说,创造“显化”。在“setup.py所在的位置”。

接下来在manifest中包含/排除所有必要的东西。这里要注意语法。 例如:假设我们有模板文件夹要包含在源包中。

在manifest文件中这样做:

recursive-include template *

确保像上面那样在文件/dirs的dir-name和pattern之间留有空格。 不要像我们在gitignore那样做

recursive-include template/* [this won't work]

其他选项是使用include。有很多选择。看看他们的Manifest.in文件

最后重要的一步是,在setup.py中包含这个参数,然后就可以开始了!

   setup(
    ...
    include_package_data=True,
    ......
)

希望有帮助!编码快乐!

这里有一个对我有用的更简单的答案。

首先,根据上面Python Dev的注释,setuptools是不需要的:

package_data is also available to pure distutils setup scripts 
since 2.3. – Éric Araujo

这很好,因为在包中添加setuptools要求意味着您也必须安装它。简而言之:

from distutils.core import setup

setup(
    # ...snip...
    packages          = ['pkgname'],
    package_data      = {'pkgname': ['license.txt']},
)

要实现你所描述的需要两步……

需要将该文件添加到源压缩文件中 需要修改Setup.py,将数据文件安装到源路径

步骤1:要将文件添加到源tarball,请将其包含在MANIFEST中

在包含setup.py的文件夹中创建MANIFEST模板

MANIFEST基本上是一个文本文件,其中包含将包含在源tarball中的所有文件的列表。

下面是我项目的MANIFEST:

CHANGELOG.txt INSTALL.txt LICENSE.txt pypreprocessor.py 固定 setup . py test.py TODO.txt

注意:虽然sdist确实会自动添加一些文件,但我更喜欢显式地指定它们,而不是预测它能做什么,不能做什么。

步骤2:要将数据文件安装到源文件夹,请修改setup.py

由于您希望向源安装文件夹添加一个数据文件(LICENSE.txt),因此需要修改数据安装路径以匹配源安装路径。这是必要的,因为默认情况下,数据文件安装到与源文件不同的位置。

修改数据安装目录以匹配源安装目录…

从distutils中获取安装目录信息:

from distutils.command.install import INSTALL_SCHEMES

修改数据安装目录以匹配源安装目录:

for scheme in INSTALL_SCHEMES.values():
    scheme['data'] = scheme['purelib']

然后,将数据文件和位置添加到setup():

data_files=[('', ['LICENSE.txt'])]

注意:上面的步骤应该以标准的方式完成您所描述的工作,而不需要任何扩展库。