sys.path 模块搜索路径的初始化

在 Python 启动时会初始化模块搜索路径。可以在 sys.path 中访问此模块搜索路径。

模块搜索路径中的第一个条目是包含输入脚本的目录(如果存在)。否则,第一个条目是当前目录,这是在执行交互式 shell、-c 命令或 -m 模块时的情况。

通常使用 PYTHONPATH 环境变量将目录添加到搜索路径。如果找到此环境变量,则其内容将添加到模块搜索路径。

注意

PYTHONPATH 将影响所有已安装的 Python 版本/环境。请谨慎在 shell 配置文件或全局环境变量中设置此变量。site 模块提供更细致的技术,如下所述。

接下来添加的项目是包含标准 Python 模块的目录以及这些模块所依赖的任何 扩展模块。扩展模块在 Windows 上是 .pyd 文件,在其他平台上是 .so 文件。包含与平台无关的 Python 模块的目录称为 prefix。包含扩展模块的目录称为 exec_prefix

环境变量 PYTHONHOME 可用于设置 prefixexec_prefix 位置。否则,这些目录将通过使用 Python 可执行文件作为起点,然后查找各种“地标”文件和目录来找到。请注意,将遵循任何符号链接,因此实际的 Python 可执行文件位置将用作搜索起点。Python 可执行文件位置称为 home

一旦确定了 home,则首先查找 pythonmajorversionminorversion.zip (python311.zip) 来找到 prefix 目录。在 Windows 上,将在 home 中搜索 zip 存档,而在 Unix 上,该存档应位于 lib 中。请注意,即使存档不存在,预期的 zip 存档位置也会添加到模块搜索路径中。如果未找到存档,Windows 上的 Python 将继续通过查找 Lib\os.py 来搜索 prefix。Unix 上的 Python 将查找 lib/pythonmajorversion.minorversion/os.py (lib/python3.11/os.py)。在 Windows 上,prefixexec_prefix 相同,但在其他平台上,将搜索 lib/pythonmajorversion.minorversion/lib-dynload (lib/python3.11/lib-dynload) 并将其用作 exec_prefix 的锚点。在某些平台上,lib 可能为 lib64 或其他值,请参阅 sys.platlibdirPYTHONPLATLIBDIR

一旦找到,prefixexec_prefix 分别在 sys.prefixsys.exec_prefix 中可用。

最后,site 模块得到处理,site-packages 目录被添加到模块搜索路径。自定义搜索路径的常用方法是创建 sitecustomizeusercustomize 模块,如 site 模块文档中所述。

注意

某些命令行选项可能会进一步影响路径计算。有关详细信息,请参见 -E-I-s-S

虚拟环境

如果 Python 在虚拟环境中运行(如 虚拟环境和包 中所述),则 prefixexec_prefix 具体取决于虚拟环境。

如果在主可执行文件旁边或在可执行文件上一级的目录中找到 pyvenv.cfg 文件,则适用以下变体

  • 如果 home 是绝对路径,并且 PYTHONHOME 未设置,则在推断 prefixexec_prefix 时,将使用此路径,而不是主可执行文件的路径。

_pth 文件

要完全覆盖 sys.path,请创建一个与共享库或可执行文件同名的 ._pth 文件(python._pthpython311._pth)。共享库路径在 Windows 上始终已知,但在其他平台上可能不可用。在 ._pth 文件中,为要添加到 sys.path 的每个路径指定一行。基于共享库名称的文件会覆盖基于可执行文件的文件,这允许在需要时限制加载运行时的任何程序的路径。

当文件存在时,将忽略所有注册表和环境变量,启用隔离模式,并且 site 不会被导入,除非文件中的某一行指定 import site。将忽略空白路径和以 # 开头的行。每个路径可以是绝对路径,也可以是相对于文件位置的相对路径。除了 site 之外的导入语句不被允许,并且不能指定任意代码。

请注意,当指定 import site 时,site 模块将正常处理 .pth 文件(没有前导下划线)。

嵌入式 Python

如果 Python 嵌入在另一个应用程序中 Py_InitializeFromConfig(),则可以使用 PyConfig 结构来初始化 Python。路径特定详细信息在 Python 路径配置 中进行了描述。或者,可以使用较旧的 Py_SetPath() 来绕过模块搜索路径的初始化。

另请参见