每一个 Python 文件都是一个模块(module),可以在另一个 Python 文件中通过 import 导入。 如果文件位于同一目录, 可以直接使用不带限定名的 import 语句:

# module.py

def useful_function():
    return "I'm being useful!"
# use_module.py
import module

print("'module' imported")

if __name__ == "__main__":
    print(module.useful_function())
#: 'module' imported
#: I'm being useful!

导入模块后,这个模块的命名空间(namespace)就可以在当前文件中通过模块名访问。 这种机制自动避免了导入模块中的名称和本地名称发生冲突。 要调用 useful_function(),必须使用模块名对它进行限定(qualify): module.useful_function()。

use_module.py 末尾的代码以一个 if 子句开始,它检查标准变量 __name__ 是否等于字符串 "__main__"。 在 Python 中,任何以双下划线开头并以双下划线结尾的标识符 (通常称为 “dunder”)都有某种特殊含义。 例如 dunder method 会把你的类连接到语言中的运算符和内置函数 (参见07 · 类)。

之所以存在这个 if,是因为任何文件也都可以作为 library module 被另一个程序使用。 这种情况下,你只希望获得其中的定义, 而不希望文件底部的代码自动执行。 这个特定的 if 条件只会在你直接运行该文件时成立。 也就是说,当你从命令行这样运行时,__name__ 是 "__main__":

python use_module.py

但如果另一个程序把 use_module.py 作为模块导入, __name__ 就不是 "__main__",因此其中的 "__main__" 代码不会运行。 下面这个程序只导入 use_module:

# import_module.py
import use_module
#: 'module' imported

导入 use_module 会执行它的 top-level 代码,包括这个 print(), 但不会执行它的 "__main__" 代码块。 而且无论程序导入它多少次,这些代码都只运行一次:

# import_once.py
import sys
import use_module
import use_module as second

#: 'module' imported
print(use_module is second)
#: True
print(sys.modules["use_module"] is use_module)
#: True

尽管有两条 import 语句提到了 use_module,它的函数体仍然只执行一次。 第一次 import 会把完成加载的 module object 存进 sys.modules, 这是一个以 dotted module name 为 key 的 dict。 之后程序中任何文件再次 import 同一个名称时, 都会从那里找到它,并绑定到同一个对象,而不是重新运行文件, 所以 use_module 和 second 实际上是同一个对象。 由此也产生一个结果:运行中的程序不会自动注意到已经导入模块的源码发生了修改。 要么重启程序,要么调用 importlib.reload(use_module), 后者会在现有 module object 上重新运行模块体。 但 reload 之后,所有通过 from ... import 绑定的名称仍然指向旧对象, 所以重启程序才是可靠选择。

如果要把某个名称直接带进当前 namespace,使用 from 关键字:

# using_from.py
from module import useful_function

if __name__ == "__main__":
    print(useful_function())
#: I'm being useful!

from 会把这个名称当前绑定的值复制到本文件的名称绑定中,而不是建立持续链接。 之后即使模块内部重新绑定该名称,也不会影响这个本地副本:

# app_settings.py

debug: bool = False

def show() -> None:
    print(f"app_settings.debug is{debug}")
# from_snapshot.py
import app_settings
from app_settings import debug

app_settings.debug = True
print(debug, app_settings.debug)
#: False True
app_settings.show()
#: app_settings.debug is True

此时 app_settings.debug 已经是 True, 而 show() 能看到新值,因为它每次运行时都会在自己的模块中重新查找该名称。 本地 debug 则是一个独立绑定,是 from 在 import 时设置一次的, 所以它仍然保存 False。 当一个值可能变化时,应导入模块并写成 app_settings.debug。 对于会一直保持同一个值的名称,例如函数和类,可以使用 from ... import。