# 31.4. `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()`覆盖。

  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__` is set to run_name if this optional argument is not `None`, to `mod_name + '.__main__'` if the named module is a package and to the mod_name argument otherwise.

  `__spec__`将为实际导入的模块（即`__spec__.name`始终为mod_name `mod_name + '.__ main __`，永远不要run_name）。

  `__file__`, `__cached__`, `__loader__` and `__package__` are set as normal based on the module spec.

  If the argument alter_sys is supplied and evaluates to `True`, then `sys.argv[0]` is updated with the value of `__file__` and `sys.modules[__name__]` is updated with a temporary module object for the module being executed. 在函数返回之前，`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)

  在指定的文件系统位置执行代码，并返回结果模块全局字典。与提供给CPython命令行的脚本名称一样，提供的路径可以指代包含`__main__`模块的Python源文件，编译后的字节码文件或有效的sys.path条目。一个包含顶层`__main__.py`文件的zip文件）。

  对于简单的脚本，指定的代码只是在一个新的模块命名空间中执行。对于有效的sys.path条目（通常为zipfile或目录），该条目首先添加到`sys.path`的开头。然后，该函数使用更新的路径查找并执行`__main__`模块。请注意，如果在指定位置没有此类模块，则不会调用位于`sys.path`上其他位置的现有`__main__`条目的特殊保护。

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

  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`和`'<run_path>'`，则`__name__`设置为run_name。

  如果提供的路径直接引用脚本文件（无论是作为源或预编译的字节代码），则`__file__`将设置为提供的路径，`__spec__`，`__cached__`，`__loader__`和`__package__`将全部设置为`None`。

  If the supplied path is a reference to a valid sys.path entry, then `__spec__` will be set appropriately for the imported `__main__` module (that is, `__spec__.name` will always be `__main__`). `__file__`，`__cached__`，`__loader__`和`__package__`将被设置为set as normal

  还对`sys`模块进行了许多更改。首先，可以如上所述改变`sys.path`。`sys.argv[0]` is updated with the value of `file_path` and `sys.modules[__name__]` is updated with a temporary module object for the module being executed. 在`sys`中对项目的所有修改都会在函数返回之前还原。

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

  也可以看看

  Interface options用于命令行上的等效功能（`python path / to / script`）。

  版本3.2中的新功能。

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

也可以看看

PEP 338 - 将模块作为脚本执行
  PEP由Nick Coghlan编写和实施。
PEP 366 - 主模块显式相对导入
  PEP由Nick Coghlan编写和实施。
PEP 451 - 导入系统的ModuleSpec类型
  PEP由Eric Snow编写和实施

Command line and environment - CPython命令行详细信息

`importlib.import_module()`函数