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)¶ 执行给定模块的代码,并返回结果模块的 globals 字典。 该模块的代码首先会用标准的导入机制去查找定位 (详情请参阅 PEP 302),然后在全新的模块命名空间中运行。
参数 mod_name 应该是一个绝对模块名。如果模块名指向一个包,而不是普通的模块,那么该包会被导入,然后执行包中的
__main__子模块,并返回结果模块的 globals 字典。可选的字典参数 init_globals 可用来在代码执行前预填充模块的 globals 字典。给出的字典参数不会被修改。如果字典中定义了以下任意一个特殊全局变量,这些定义都会被
run_module()覆盖。The special global variables
__name__,__spec__,__file__,__cached__,__loader__and__package__are set in the globals dictionary before the module code is executed (Note that this is a minimal set of variables - other variables may be set implicitly as an interpreter implementation detail).若可选参数
__name__不为None则设为 run_name,若此名称的模块是一个包则设为mod_name + '.__main__',否则设为 mod_name 参数。__spec__将设为合适的 实际 导入模块(也就是说,__spec__.name一定是 mod_name 或mod_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的形式访问。
-
runpy.run_path(file_path, init_globals=None, run_name=None)¶ 执行指定位置的代码,并返回结果模块的 globals 字典。与提供给 CPython 命令行的脚本名称一样,给出的路径可以指向 Python 源文件、编译过的字节码文件或包含``__main__`` 模块的有效 sys.path 项(例如一个包含顶级``__main__.py`` 文件的 zip 文件)。
对于直接的脚本而言,指定代码将直接在一个新的模块命名空间中运行。对于一个有效的 sys.path 项(通常是一个 zip 文件或目录),其首先会被添加到
sys.path的开头。然后,本函数用更新后的路径查找并执行__main__模块。请注意,即便在指定位置不存在主模块,也没有特别的保护措施来防止调用存在于sys.path其他地方的__main__。利用可选的字典参数 init_globals ,可在代码执行前预填模块的 globals 字典。给出的字典参数不会被修改。如果给出的字典中定义了下列特殊全局变量,这些定义均会被
run_module()覆盖。The special global variables
__name__,__spec__,__file__,__cached__,__loader__and__package__are set in the globals dictionary before the module code is executed (Note that this is a minimal set of variables - other variables may be set implicitly as an interpreter implementation detail).如果该可选参数不为
None,则__name__被设为 run_name,否则为'<run_path>'。如果提供的路径直接引用了一个脚本文件(无论是源码文件还是预编译的字节码),那么
__file__将设为给出的路径,而__spec__、__cached__、__loader__和__package__都将设为None。如果给出的路径是对有效 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__。
