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

时间:2017-01-26 10:17:37

标签: python python-3.x import namespaces python-module

我的问题是编写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的方式来定义命名空间吗?或者是否有更好/通用的方法来组织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'

2 个答案:

答案 0 :(得分:5)

  

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

这是设置Python包的 okay 方法。由于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问题的范围内,但这里有一些问题,这是一个深思熟虑的问题:

答案 1 :(得分:3)

第二个问题的答案:

在文件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