使 Python 中的 distutils 自动查找包

Posted

技术标签:

【中文标题】使 Python 中的 distutils 自动查找包【英文标题】:make distutils in Python automatically find packages 【发布时间】:2012-10-09 14:15:09 【问题描述】:

当在 Python 中的 distutils 中的 setup.py 中描述 python 包时,有没有办法让它自动获取每个包含 __init__.py 的目录并将其作为子包包含在内?

即如果结构是:

mypackage/__init__.py
mypackage/a/__init__.py
mypackage/b/__init__.py

我想避免这样做:

packages = ['mypackage', 'mypackage.a', 'mypackage.b']

而只是这样做:

packages = ['mypackage']

并让它自动找到像 ab 这样的东西,因为它们有一个 init 文件。谢谢。

【问题讨论】:

如果这样做,请确保在构建之前不要让任何垃圾堆积在包结构中。 【参考方案1】:

最简单的方法(据我所知)是使用pkgutil.walk_packages 来生成包:

from distutils.core import setup
from pkgutil import walk_packages

import mypackage

def find_packages(path=__path__, prefix=""):
    yield prefix
    prefix = prefix + "."
    for _, name, ispkg in walk_packages(path, prefix):
        if ispkg:
            yield name

setup(
    # ... snip ...
    packages = list(find_packages(mypackage.__path__, mypackage.__name__)),
    # ... snip ...
)

【讨论】:

可能(确实,很可能)更好的方法来做到这一点......我只是不知道他们(还):-) setuptools 中的find_packages() 本质上完全相同,请参阅我的答案 @dm76 是的,但 OP 要求的是 distutils,而不是 setuptools。我错过了什么吗? __path__ 回复我NameError,我改用'.' 投反对票 - 你能解释一下,以便我可以更好地回答吗?【参考方案2】:

我建议使用 setuptools 提供的 find_packages() 函数,例如:

from setuptools import setup, find_packages

然后做

packages=find_packages()

【讨论】:

请注意,find_packages() 找不到 > 3.3 样式的 no-init.py 包。关于这个问题的票是bitbucket.org/pypa/setuptools/issue/97。所以现在,需要在包中添加__init__.py 文件以供find_packages() 自动收集,或者必须在packages 中显式命名。 更新:如果在 Python 3.3 (package init file 'mymod/mysubmod/__init__.py' not found (or not a regular file)) 上不使用 __init__.py 文件,即使是显式列表也会出现问题。 现在还有find_namespace_packages()(参见setuptools.readthedocs.io/en/latest/…)可与PEP 420 命名空间包(python.org/dev/peps/pep-0420)一起使用【参考方案3】:
import re, os
def find_packages(path='.'):
    ret = []
    for root, dirs, files in os.walk(path):
        if '__init__.py' in files:
            ret.append(re.sub('^[^A-z0-9_]+', '', root.replace('/', '.')))
    return ret

setup(
...
packages = find_packages()
...
)

【讨论】:

【参考方案4】:

与 dm76 答案相同,只是我的 repo 中也有测试,所以我使用:

from setuptools import find_packages

packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]),

【讨论】:

以上是关于使 Python 中的 distutils 自动查找包的主要内容,如果未能解决你的问题,请参考以下文章

win7中的python文件pydistutils.cfg文件在哪里?

基于Cython和内置distutils库,实现python源码加密(非混淆模式)

ImportError:无法从“distutils”(/usr/lib/python3.8/distutils/__init__.py)导入名称“sysconfig”

如何使用 distutils 安装 Python 扩展模块?

使用 distutils / setuptools 执行 Python 脚本安装后

使用 distutils / setuptools 执行 Python 脚本安装后