Python 在包中导入模块

Python Importing modules in a package

我目前创建了一个具有许多功能的模块。
它变得相当大,所以我想我应该把它做成一个包并将功能拆分,使其更易于管理。

我只是在真正这样做之前测试这一切是如何工作的,如果它看起来有点脆弱,我们深表歉意。
我创建了一个名为 pack_test 的文件夹,其中包含:
__init__.py
foo.py
bar.py


__init__.py 包含:

__all__ = ['foo', 'bar']
from . import *
import subprocess
from os import environ

在控制台我可以写 import pack_test as pt 这很好,没有错误。
pt. 和两个选项卡显示我可以在其中看到 pt.barpt.environpt.foopt.subprocess
目前一切顺利。


如果我想在 foo.pybar.py 中引用 subprocessenviron 我该怎么做?

如果在 bar.py 中,我有一个只执行 return subprocess.call('ls') 的函数,它会出错说 NameError: name 'subprocess' is not defined。一定有一些我遗漏的东西使我能够从上面的级别引用子流程吗?据推测,一旦我可以从中获得语法,我也可以用类似的方式调用 environ 吗?

我看到的另一种选择是在 foo.pybar.py 中都包含 import subprocess 但是让它出现在多个文件中对我来说似乎有点奇怪当我可以在更高级别拥有一次时,特别是如果我继续拥有大量文件而不是本例中的 2 个文件。

您可以创建 modules.py 包含

import subprocess
import os

然后在 foo.py 或您的任何文件中都有。

from modules import *

您文件中的导入语句然后是静态的,并且只需更新 modules.py 当您想要添加一个可供所有人访问的附加模块时。

长话短说:

__init__.py :

import foo
import bar

__all__ = ["foo", "bar"]

foo.py:

import subprocess
from os import environ

# your code here

bar.py

import subprocess
from os import environ

# your code here

There must be something I'm missing which enables me to reference subprocess from the level above?

不,这是预期的行为。

import 加载一个模块(如果尚未加载),将其缓存在 sys.modules 中(同上),并将导入的名称绑定到当前命名空间中。每个 Python 模块都有(或 "is")它自己的命名空间(没有真正的 "global" 命名空间)。 IOW,你必须在 each 模块中导入你需要的东西,即如果 foo.py 需要 subprocess,它必须明确地导入它。

一开始这看起来有点乏味,但从长远来看 运行 它确实有助于提高可维护性 - 您只需阅读模块顶部的导入(pep 08:始终将所有导入在模块的开头)以了解名称的来源。

此外,您不应在 python shell 以外的任何其他地方使用星号导入(又名通配符导入又名 from xxx import *)(即使那样......) - 这是一个维修定时炸弹。不仅因为您不知道每个名称的来源,还因为它是重新绑定已导入名称的可靠方法。假设您的 foo 模块定义了函数 "func"。某处你有 "from foo import *; from bar import *",然后在代码中调用 func。现在有人编辑 bar.py 并添加了一个(不同的)"func" 函数,突然您调用失败了,因为您没有调用预期的 "func"。现在享受调试吧......现实生活中的例子通常比这复杂一点。

所以如果你喜欢你的精神健全,不要偷懒,也不要试图变得聪明,只需做一件简单明显的事情:在你的模块顶部明确地导入你感兴趣的名字.

(到过这里,做过那个等等)