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

P. *_*ehr 4 python import namespaces python-module python-3.x

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

由于我在Python方面缺乏经验,因此很难在一个简单的问题中表达我的想法.所以让我们考虑下面的小python包作为例子.

目录布局

dir
 |
 +-- example
 |    |
 |    +-- script.py
 |
 +-- package
      |
      +-- __init__.py
      |
      +-- foo.py
      |
      +-- subpackage
           |
           +-- __init__.py
           |
           +-- bar.py
Run Code Online (Sandbox Code Playgroud)

我们来看看这些文件.

文件内容

package/foo.py:

def foo:
    print('foo')
Run Code Online (Sandbox Code Playgroud)

package/subpackage/bar.py:

def bar:
    print('bar')
Run Code Online (Sandbox Code Playgroud)

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

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

import package
import package.subpackage


package.foo.foo()
package.subpackage.bar.bar()
Run Code Online (Sandbox Code Playgroud)

我不喜欢使用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
Run Code Online (Sandbox Code Playgroud)

package/subpackage/__init__.py:

from package.subpackage.bar import bar
Run Code Online (Sandbox Code Playgroud)

问题

  • 这是一种类似python的方式来定义命名空间吗?或者是否有更好/通用的方法来组织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 "..\package\subpackage\__init__.py", line x, in <module>
from subpackage.bar import bar
ImportError: No module named 'subpackage'
Run Code Online (Sandbox Code Playgroud)

小智 6

第二个问题的答案:

在 file 中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


ane*_*oid 5

这是一种类似python的方式来定义命名空间吗?或者是否有更好/通用的方法来组织python中的包的文件系统.(我没有为此找到合适的教程/示例.)

这是设置Python包的好方法.只有好和的,因为内容不是"好" foo.py和bar.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().它也可以通过__all__在init中使用来完成,但import *也不被认为是好的.

或者,foo和bar包应该有更多的像foo.function1,foo.other_func,bar.drink等这使得它更加人性化理解的组织.

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