在Python中,是否可以在包级别公开子包中的模块?

时间:2016-06-30 18:38:13

标签: python python-2.7 python-import python-packaging

我有以下难题。我试图在父包级别从包的子包中公开一些模块。

文件夹结构基本上是这样的:

script.py
package/
    __init__.py
    module1.py
    subpackage/
        __init__.py
        submodule1.py
        submodule2.py

在我目前必须编写的script.py文件中

from package.subpackage.submodule1 import foo

如果我想从submodule1.py文件中导入某些内容,但我希望能够在包级别公开文件submodule1.pysubmodule2.py,这样我的所有导入都可以看起来像

from package.module1 import bar
from package.submodule1 import foo
from package.submodule2 import goo

请注意,我不想在bar级别公开foogoopackage,即

from package import bar
from package import foo

因为在我的情况下,模块之间的分离仍然很重要。

这甚至可能吗? __init__.py文件中有诀窍吗?

谢谢!

2 个答案:

答案 0 :(得分:5)

为了您的目的,python模块只是名称空间。也就是说,模块的全局变量中的所有内容都可以导入并用作module.thingy。您可能已经注意到,在许多模块中,您还可以找到一些内置函数。例如,logging.os只是常规os模块。

因此,在您的包(package/__init__.py)中导入您想要的任何内容,并将其绑定到您要将其公开为的名称。

# package/__init__.py
# import package.module1 as module1  # one *can* do this, but its at best without benefit (see comments)
import package.subpackage.submodule1 as submodule1
import package.subpackage.submodule2 as submodule2

这样可以import package.submodule1import package.submodule1 as foo

请注意,这种简单的方式允许您执行from package.submodule1 import bar。为此,您需要一个实际的虚拟模块。

# package/submodule1/__init__.py
from package.subpackage.submodule1 import *

答案 1 :(得分:3)

是的,这是可能的 让我们一步一步看看会发生什么;

  1. 当您执行from package.submodule1 import foo时,会检查sys.modules是否有package
  2. 如果未找到package/__init__.py正在运行并加载
  3. 再次sys.modules检查package.submodule1
  4. 如果未找到,则会检查package/submodule1.py是否存在。
  5. 我们可以在步骤2中为sys.modules package.submodule1中输入一个条目来完成第3步。

    package/__init__.py

    import sys
    from .subpackage import submodule1
    from .subpackage import submodule2
    
    for module in (submodule1, submodule2):
        full_name = '{}.{}'.format(__package__, module.__name__.rsplit('.')[-1])
        sys.modules[full_name] = sys.modules[module.__name__]