如何使用(子)模块中的__init__.py来定义命名空间?



我的问题是关于编写Python(3.x)包和(子)模块以及正确使用__init__.py文件来声明命名空间.
我曾经用C++编码,所以我喜欢使用很多单独的文件来组织项目。例如,(imo)如果模块包含多个类,则每个类都应位于单独的文件中。

由于我没有开发Python的经验,因此很难在一个简单的问题中表达我的想法。 因此,让我们以以下小型python包为例。

目录布局

dir
|
+-- example
|    |
|    +-- script.py
|
+-- package
|
+-- __init__.py
|
+-- foo.py
|
+-- subpackage
|
+-- __init__.py
|
+-- bar.py

让我们看一下文件。

文件内容

package/foo.py

def foo:
print('foo')

package/subpackage/bar.py

def bar:
print('bar')

以下example/script.py工作正常。

import sys
sys.path.insert(0, '..')
import package
import package.subpackage

package.foo.foo()
package.subpackage.bar.bar()

我不喜欢使用package.foo.foo()/package.subpackage.bar.bar(),想使用package.foo()/package.subpackage.bar()

而且我不想使用from package.subpackage.bar import bar,因为我不想将子包的命名空间混合到脚本中。

溶液

我使用__init__.py文件来实现这一点。

package/__init__.py

from package.foo import foo

package/subpackage/__init__.py

from package.subpackage.bar import bar

问题

  • 这是定义命名空间的好方法吗?或者有没有更好/通用的方法来组织 python 包的文件系统。(我没有找到合适的教程/示例。

  • 在文件package/subpackage/__init__.py中,为什么它必须是:

    from package.subpackage.bar import bar

    而不是:

    from subpackage.bar import bar

这将导致错误:

Traceback (most recent call last):
File "script.py", line x, in <module>
import package.subpackage
File "..packagesubpackage__init__.py", line x, in <module>
from subpackage.bar import bar
ImportError: No module named 'subpackage'

这是定义命名空间的好方法吗?或者有没有更好/通用的方法来组织 python 包的文件系统。(我没有找到合适的教程/示例。

这是设置 Python 包的方法。只有好而不是">",因为foo.pybar.py的内容.

我不喜欢使用package.foo.foo()/package.subpackage.bar.bar(),想使用package.foo()/package.subpackage.bar()

在这种情况下,你不能。不混合命名空间是不这样做的好理由from package.subpackage.bar import bar.

如果def foo(): ...def bar(): ...直接在__init__.py会更好.这样,您就可以完成package.foo()package.subpackage.bar()。也可以通过在 init 中使用__all__来完成import *但也不被认为是好的。

或者,foobar包应该包含更多,如foo.function1foo.other_funcbar.drink等,这给了它更人性化的可理解的组织。

示例和参考不在好的 StackOverflow 问题范围内,但这里有一些,对于一个经过深思熟虑的问题:

  • 构建你的项目 — Python的顺风车指南
  • 组织模块和包的 Python 方式
  • 如何组织一个Python项目?

第二个问题的答案:

在文件package/subpackage/__init__.py中,为什么它必须是:

from package.subpackage.bar import bar

而不是:

from subpackage.bar import bar

是你必须使用from .bar import bar.当您要在包结构内执行相对导入时,将使用点。请参阅:https://docs.python.org/3/tutorial/modules.html#intra-package-references

最新更新