14

我想在一个主模块中有几个 python 子模块,但我想将它们作为单独的 python 包分发。所以包A应该提供'my_data.source_a',包B应该提供'my_data.source_b',......等等。

我发现我必须为此使用命名空间包,但试图弄清楚细节,我发现多个 PEP 涵盖了该问题。PEP 420 似乎是最新的,它建立在 PEP 402 和 PEP 382 之上。

对我来说,不清楚不同 PEP 的实施状态是什么。所以我的问题是: http: //pythonhosted.org/distribute/setuptools.html#namespace-packages仍然是要走的路还是我应该如何构建我的命名空间包?

4

2 回答 2

10

Python 文档很好地描述了在Python 中创建命名空间包的三种方法,包括何时使用这三种方法的指南。此外,该主题在另一个 StackOverflow线程中进行了深入讨论,该线程具有良好的接受答案。最后,如果您喜欢阅读代码而不是文档,那么sample-namespace-packagesrepo 包含使用三种可用方法中的每一种创建的命名空间包的示例。

简而言之,如果您希望您的包与 Python 3.3 及更高版本一起使用,您应该使用本机命名空间包方法。如果您希望您的包与旧版本的 Python 一起使用,您应该使用pkgutil方法. 如果您打算将命名空间包添加到已经在使用pkg_resourcesmethod的命名空间,则应继续使用 method.


使用本机命名空间包,我们可以__init__.py从两个包中删除并修改我们的setup.py文件,如下所示:

# setup.py file for my_data.source_a
from setuptools import setup, find_namespace_packages

setup(
    name="my_data.source_a",
    version="0.1",
    packages=find_namespace_packages(include=['my_data.*'])
)
# setup.py file for my_data.source_b
from setuptools import setup, find_namespace_packages

setup(
    name="my_data.source_b",
    version="0.1",
    packages=find_namespace_packages(include=['my_data.*'])
)

我们需要添加include=['my_data.*']参数,因为默认情况下find_namespace_packages(),它在作为命名空间包包含的文件夹中相当宽松,如此处所述

这是支持 Python 3.3 及更高版本的软件包的推荐方法。


使用pkgutil-style 命名空间包,我们需要将以下行添加到每个包my_data.__init__.py中的文件中:

__path__ = __import__('pkgutil').extend_path(__path__, __name__)

这是backports命名空间和 repo 中不同包使用的google-cloud-python方法,也是支持旧版本 Python 的推荐方法。

于 2016-08-31T03:30:32.910 回答
4

最新版本的 Python 是 Python 3.7 使用本机命名空间包方法来创建在PEP 420中定义的命名空间包。

目前有三种不同的方法来创建命名空间包:

  1. 使用本机命名空间包。这种类型的命名空间包在PEP 420中定义,在 Python 3.3 及更高版本中可用。如果您的命名空间中的包只需要支持 Python 3 并通过pip.
  2. 使用pkgutil 风格的命名空间包。对于需要支持 Python 2 和 3 并通过 和 安装的新包,建议使用此pip方法python setup.py install
  3. 使用pkg_resources 风格的命名空间包。如果您需要与已经使用此方法的包兼容,或者您​​的包需要是 zip 安全的,则建议使用此方法。

参考:打包命名空间包

于 2019-08-10T20:03:22.123 回答