如何使用 setuptools 和 setup.py 从包中排除单个文件

Posted

技术标签:

【中文标题】如何使用 setuptools 和 setup.py 从包中排除单个文件【英文标题】:How to exclude a single file from package with setuptools and setup.py 【发布时间】:2016-05-09 00:57:37 【问题描述】:

我正在处理blowdrycss。存储库是here。

我希望将 blowdrycss_settings.py 的设置文件从 pypi 的最终包中排除。目的是动态构建一个自定义设置文件,该文件将放置在用户 virtualenv / 项目文件夹中。

setup.py,我有以下内容:

packages=find_packages(exclude=['blowdrycss_settings.py', ]),

我也试过exclude_package_data:

exclude_package_data=
    '': ['blowdrycss_settings.py'],
    '': ['blowdrycss/blowdrycss_settings.py'],
    'blowdrycss': ['blowdrycss_settings.py'],
,

然后我运行python setup.py sdist bdist

但是,当我查看构建文件夹时,我仍然看到blowdrycss_settings.py

- build 
    - lib
        - blowdrycss_settings.py

似乎只排除一个文件应该很简单。

如何从分发包中排除blowdrycss_settings.py

【问题讨论】:

您是否尝试过使用exclude_package_data 我没有。我不知道它的存在。 我正在使用以下exclude_package_data='': ['blowdrycss_settings.py'], ,,但它仍然没有根据需要排除该文件。 【参考方案1】:

这是我的解决方案。

blowdrycss 下,我创建了一个名为settings 的新模块,因此目录结构现在如下所示:

blowdrycss
    blowdrycss
        settings
            blowdrycss_settings.py

基于此reference,在setup.py 内部,我有以下内容:

packages=find_packages(exclude=['*.settings', ]),   

构建发行版:

    删除builddist.egg-info 文件夹。 运行python setup.py sdist bdist

回想起来,我无法做我最初尝试的事情是件好事。新结构感觉更干净,更模块化。

【讨论】:

第一步不应在子条款中提及。这是一个非常重要的步骤,也是关于 setuptools 或 distutils 的一个非常烦人的情况,它分别引入了历史文物。【参考方案2】:

假设你有一个项目

root
├── setup.py
└── spam
    ├── __init__.py
    ├── bacon.py
    └── eggs.py

并且您想从包装中排除 spam/eggs.py

import fnmatch
from setuptools import find_packages, setup
from setuptools.command.build_py import build_py as build_py_orig


excluded = ['spam/eggs.py']


class build_py(build_py_orig):
    def find_package_modules(self, package, package_dir):
        modules = super().find_package_modules(package, package_dir)
        return [
            (pkg, mod, file)
            for (pkg, mod, file) in modules
            if not any(fnmatch.fnmatchcase(file, pat=pattern) for pattern in excluded)
        ]


setup(
    packages=find_packages(),
    cmdclass='build_py': build_py
)

excluded 列表中的 Glob 和多个条目也可以工作,因为它被 fnmatch 使用,所以你可以例如声明

excluded = [
    'modules_in_directory/*.py',
    'modules_in_subtree/**/*.py',
    'path/to/other/module.py'
]

等等

本食谱基于my other answer 到问题setup.py exclude some python files from bdist 。不同之处在于,这个配方排除了基于文件 glob 的模块,而另一个排除了基于 qualnames 的模块,例如

excluded = ['spam.*', '*.settings']

将排除spam包的所有子模块以及每个包和子包等中名为settings的所有模块。

【讨论】:

【参考方案3】:

从带有setuptools 的包中删除单个 或至少几个特定文件的最简单方法就是使用MANIFEST.in。例如,在一个包中,您可以通过简单地指定global-exclude foo.py 来排除所有文件名foo.py。如果您只使用MANIFEST.in 方法,则无需setuptools 破解或更改包的结构。

查看专用的PyPA article on using MANIFEST.in 了解更多您可以使用的命令。

【讨论】:

以上是关于如何使用 setuptools 和 setup.py 从包中排除单个文件的主要内容,如果未能解决你的问题,请参考以下文章

如何获得 setuptools 和 easy_install?

win7下python2.6如何安装setuptools和pip

python setuptools 打包 发布

Centos6.5 自带的Python2.6.6 如何安装setuptools和pip

如何使用 setuptools 生成调用 `python -m mypackage` 的 console_scripts 入口点?

如何将安装后脚本添加到 easy_install / setuptools / distutils?