10

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

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

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,foogoo级别package,即

from package import bar
from package import foo

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

这甚至可能吗?文件中是否有__init__.py这样做的技巧?

谢谢!

4

2 回答 2

10

出于您的目的,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 *
于 2016-06-30T18:44:46.843 回答
6

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

  1. 当你这样做时from package.submodule1 import foosys.modules检查它是否有package
  2. 如果未找到package/__init__.py,则运行并加载
  3. 再次sys.modules检查package.submodule1
  4. 如果未找到,package/submodule1.py则检查是否存在。

sys.modules我们可以通过在第 2 步中输入for来使第 3 步通过package.submodule1

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__]
于 2016-07-01T19:27:54.333 回答