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 可用于在代码执行之前预填充模块的全局字典。init_globals 不会被修改。如果以下任何特殊全局变量在 init_globals 中定义,则这些定义将被 run_module() 覆盖。

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

如果可选参数 run_name 不为 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 命令行的脚本名称一样,file_path 可以指向 Python 源文件、编译后的字节码文件或包含 __main__ 模块的有效 sys.path 条目(例如,包含顶级 __main__.py 文件的 zip 文件)。

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

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

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

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

如果 file_path 直接引用脚本文件(无论是源文件还是预编译字节码),则 __file__ 将设置为 file_path,并且 __spec____cached____loader____package__ 都将设置为 None

如果 file_path 是对有效 sys.path 条目的引用,则 __spec__ 将为导入的 __main__ 模块进行适当设置(也就是说,__spec__.name 将始终为 __main__)。__file____cached____loader____package__ 将根据模块规范正常设置

sys 模块也进行了一些更改。首先,sys.path 可能会如上所述进行更改。sys.argv[0] 将更新为 file_path 的值,并且 sys.modules[__name__] 将更新为正在执行模块的临时模块对象。在函数返回之前,对 sys 中项目的所有修改都将还原

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

参见

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

在 3.2 版本加入。

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

3.12 版中已变更: __cached__, __loader____package__ 的设置已弃用。

参见

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

由 Nick Coghlan 撰写和实现。

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

由 Nick Coghlan 撰写和实现。

PEP 451 – 导入系统的 ModuleSpec 类型

由 Eric Snow 撰写和实现

命令行和环境 - CPython 命令行详情

importlib.import_module() 函数