runpy — 定位和执行 Python 模块

源代码: Lib/runpy.py


runpy 模块用于定位和运行 Python 模块,而无需先导入它们。其主要用途是实现 -m 命令行开关,该开关允许使用 Python 模块命名空间(而不是文件系统)来定位脚本。

请注意,这不是一个沙盒模块 - 所有代码都在当前进程中执行,并且任何副作用(例如其他模块的缓存导入)将在函数返回后仍然存在。

此外,runpy 函数返回后,由执行的代码定义的任何函数和类都不能保证正常工作。如果给定的用例不能接受此限制,则 importlib 可能比此模块更合适。

runpy 模块提供两个函数

runpy.run_module(mod_name, init_globals=None, run_name=None, alter_sys=False)

执行指定模块的代码并返回模块全局字典。首先使用标准导入机制找到模块的代码(详情请参阅PEP 302),然后在新的模块命名空间中执行。

mod_name 参数应为绝对模块名称。如果模块名称引用的是包而不是普通模块,则导入该包,然后执行该包中的 __main__ 子模块,并返回模块全局字典。

可选字典参数 init_globals 可用于在执行代码之前预填充模块的全局字典。提供的字典不会被修改。如果在提供的字典中定义了以下任何特殊全局变量,则这些定义将被 run_module() 覆盖。

在执行模块代码之前,在全局字典中设置特殊全局变量 __name____spec____file____cached____loader____package__(请注意,这是一个最小的变量集 - 其他变量可能隐式设置,作为解释器实现细节)。

如果此可选参数不是 None,则 __name__ 设置为 run_name;如果命名的模块是包,则设置为 mod_name + '.__main__';否则,设置为 mod_name 参数。

__spec__ 将根据实际导入的模块进行适当设置(即,__spec__.name 始终为 mod_namemod_name + '.__main__',永远不会是 run_name)。

__file____cached____loader____package__ 根据模块规范 正常设置

如果提供了参数 alter_sys 且其值为 True,则 sys.argv[0] 将使用 __file__ 的值更新,sys.modules[__name__] 将使用要执行的模块的临时模块对象更新。在函数返回之前,sys.argv[0]sys.modules[__name__] 都将恢复为其原始值。

请注意,对 sys 的此操作不是线程安全的。其他线程可能会看到部分初始化的模块,以及已更改的参数列表。建议在从线程代码调用此函数时不要修改 sys 模块。

另请参阅

从命令行提供等效功能的 -m 选项。

在版本 3.1 中更改: 添加了通过查找 __main__ 子模块来执行包的功能。

在版本 3.2 中更改: 添加了 __cached__ 全局变量(请参阅 PEP 3147)。

在版本 3.4 中更改: 更新以利用 PEP 451 添加的模块规范功能。这允许为通过此方式运行的模块正确设置 __cached__,并确保始终可以作为 __spec__.name 访问真实的模块名称。

在版本 3.12 中更改: 设置 __cached____loader____package__ 已弃用。有关替代方案,请参阅 ModuleSpec

runpy.run_path(path_name, init_globals=None, run_name=None)

执行指定文件系统位置的代码,并返回结果模块全局字典。与提供给 CPython 命令行的脚本名称一样,提供的路径可以引用 Python 源文件、已编译字节码文件或包含 __main__ 模块(例如,包含顶级 __main__.py 文件的 zip 文件)的有效 sys.path 条目。

对于一个简单的脚本,指定的代码只是在一个新的模块命名空间中执行。对于一个有效的 sys.path 条目(通常是一个 zipfile 或目录),该条目首先被添加到 sys.path 的开头。然后,该函数使用更新后的路径查找并执行 __main__ 模块。请注意,如果在 sys.path 的其他位置存在一个现有的 __main__ 条目,并且在指定的位置没有这样的模块,则没有特殊的保护来防止调用该条目。

可选的字典参数 init_globals 可用于在执行代码之前预填充模块的全局字典。所提供的字典不会被修改。如果在提供的字典中定义了以下任何特殊全局变量,则这些定义将被 run_path() 覆盖。

在执行模块代码之前,在全局字典中设置特殊全局变量 __name____spec____file____cached____loader____package__(请注意,这是一个最小的变量集 - 其他变量可能隐式设置,作为解释器实现细节)。

__name__ 被设置为 run_name,如果此可选参数不是 None,否则被设置为 '<run_path>'

如果提供的路径直接引用一个脚本文件(无论是作为源代码还是作为预编译的字节码),那么 __file__ 将被设置为提供的路径,并且 __spec____cached____loader____package__ 都将被设置为 None

如果提供的路径是对一个有效的 sys.path 条目的引用,那么 __spec__ 将被适当地设置为导入的 __main__ 模块(即,__spec__.name 将始终为 __main__)。__file____cached____loader____package__根据模块规范正常设置

sys 模块也进行了一些更改。首先,sys.path 可以按上述方式进行更改。使用 path_name 的值更新 sys.argv[0],并使用要执行的模块的临时模块对象更新 sys.modules[__name__]。在函数返回之前,将还原对 sys 中项的所有修改。

请注意,与 run_module() 不同,对 sys 所做的更改在此函数中不是可选的,因为这些调整对于允许执行 sys.path 条目至关重要。由于线程安全限制仍然适用,因此在带线程的代码中使用此函数应使用导入锁进行序列化或委托给单独的进程。

另请参阅

界面选项 用于在命令行上获得等效的功能(python path/to/script)。

在 3.2 版中添加。

在 3.4 版中更改: 更新以利用 PEP 451 添加的模块规范功能。这允许在从有效的 sys.path 条目导入 __main__ 而不是直接执行 __main__ 的情况下正确设置 __cached__

在 3.12 版中更改: 设置 __cached____loader____package__ 已弃用。

另请参阅

PEP 338 – 将模块作为脚本执行

由 Nick Coghlan 编写和实现的 PEP。

PEP 366 – 主模块显式相对导入

由 Nick Coghlan 编写和实现的 PEP。

PEP 451 – 导入系统的模块规范类型

由 Eric Snow 编写和实现的 PEP

命令行和环境 - CPython 命令行详细信息

importlib.import_module() 函数