site --- 站点专属的配置钩子¶
源代码: Lib/site.py
这个模块将在初始化时被自动导入。 此自动导入可以通过使用解释器的 -S 选项来屏蔽。
导入此模块时,通常会将站点特定路径追加到模块搜索路径中,并将 callables (包括 help())添加到内置命名空间中。然而,Python 启动选项 -S 会阻止这一操作;因此,可以安全地导入此模块,而无需自动修改模块搜索路径或向内置模块中添加内容。如需显式触发通常的站点特定添加操作,请调用 main() 函数。
在 3.3 版本发生变更: 在之前即便使用了 -S,导入此模块仍然会触发路径操纵。
它会以一个头部和一个尾部来构造至多四个目录作为起点。对于头部,它将使用 sys.prefix 和 sys.exec_prefix;空的头部会被跳过。对于尾部,它将使用空字符串然后是 lib/site-packages (在 Windows 上) 或 lib/pythonX.Y[t]/site-packages (在 Unix 和 macOS 上)。 (可选后缀 "t" 表示 free-threaded build,并会在 "t" 存在于 sys.abiflags 常量中时被添加。) 对于每个不同的头部 - 尾部组合,它会查看其是否指向现有的目录,如果确实如此,则将其添加到 sys.path 并且还会检查新添加目录中的配置文件。
在 3.5 版本发生变更: 对 "site-python" 目录的支持已被移除。
在 3.13 版本发生变更: 在 Unix 上,自由线程 Python 安装版是在版本专属的目录名称中以 "t" 后缀来标识的,例如 lib/python3.13t/。
在 3.14 版本发生变更: site 不再负责在 虚拟环境 上更新 sys.prefix 和 sys.exec_prefix;该操作现将在 path initialization 期间完成。因此,在 虚拟环境、sys.prefix 和 sys.exec_prefix 下,这些项不再依赖于 site 的初始化,从而也不会受 -S 的影响。
在 virtual environment 下运行时,系统会检查 sys.prefix 中的 pyvenv.cfg 文件,以检测站点特定配置。如果 include-system-site-packages 键存在且被设置为 true (不区分大小写),则会在系统级前缀中搜索 site-packages;否则则不会进行搜索。如果未对系统级前缀进行搜索,则默认也不会对用户站点前缀中的 site-packages 进行搜索。
site 模块可识别两种启动配置文件:用于路径配置的 name.pth 格式文件,以及用于首次行代码执行前处理的 name.start 格式文件。这两类文件均可存在于上述四个目录中的任一目录内。在每个目录中,这些文件会按文件名按字母顺序排序,随后按排序后的顺序进行解析。
Path extensions (.pth files)¶
name.pth 包含需要追加到 sys.path 的额外项目(每行一个)。以不存在目录命名的项目永远不会被添加到 sys.path 中,也不会进行任何检查以确认该项目指向的是目录而非文件。同一项目不会在 sys.path 中重复添加。空行以及以 # 开头的行将被跳过。
为保持向下兼容,以 import (后跟空格或制表符) 开头的行将用 exec() 来执行。
在 3.13 版本发生变更: 现在 .pth 文件会首先使用 UTF-8 来解码,如果失败会再改用 locale encoding 来解码。
在 3.15 版本发生变更: 以 import 开头的 .pth 文件行已弃用。在弃用期间,此类行仍会执行(以下情况除外),但仅当设置 -v 标志时才会发出诊断消息。
当存在 matching name.start 文件时,name.pth 中的 import 行将被静默忽略。
单行错误不再导致文件其余部分的处理中止。每个错误都会被报告,随后继续处理剩余行。
从 3.15 版起已弃用,将在 3.20 版中移除: 在 Python 3.15 中,使用除 utf-8-sig 以外的任何编码解码 name.pth 文件将被弃用;而支持从本地化编码进行解码的功能也将在 Python 3.20 中移除。
name.pth 文件中的 import 行已弃用,在 Python 3.18 和 3.19 中将被静默忽略。在 Python 3.20 中,name.pth 文件中的 import 行将触发警告。
Startup entry points (.start files)¶
在 3.15 版本加入.
启动入口文件是一种名称格式为 name.start、且存在于上述某个 site-packages 目录中的文件。每个文件通过 pkgutil.resolve_name() 所理解的 pkg.mod:callable 语法,指定在解释器启动期间需要调用的入口点。
每行非空行若不以 # 开头,则必须包含一个格式为 pkg.mod:callable 的入口点引用。冒号及可调用部分为必填项。每个可调用项均以无参数形式调用,且任何返回值均会被丢弃。
.start 文件会在所有 .pth 路径扩展被应用于 sys.path 之后进行处理,从而确保在任何启动代码运行之前,相关路径已就绪。
与来自 .pth 文件的 sys.path 扩展不同,重复的入口点**不会**被去重——如果某个入口点出现多次,它将被调用多次。
如果在解析或调用入口点过程中发生异常,则会向 sys.stderr 打印一条回溯信息,随后继续处理剩余的入口点。
.start 文件必须使用 UTF-8 编码。
PEP 829 定义了这些特性的原始规范说明。
备注
如果与具有相同基名的 name.pth 文件并存有 name.start 文件,则 .pth 文件中的任何 import 行将被忽略,转而采用 .start 文件中的入口点。
备注
可执行行(name.pth 文件中的 import 行以及 name.start 文件入口点)始终会在 Python 启动时执行(除非通过设置 -S 来完全禁用 site.py 模块);无论某个特定模块是否会被实际使用,都会执行这些行。
备注
name.start 文件会调用 pkgutil.resolve_name(),并传入 strict=True;这要求提供完整的 pkg.mod:callable 表单。
启动文件示例¶
例如,假设 sys.prefix 和 sys.exec_prefix 被设置为 /usr/local。随后,在 /usr/local/lib/pythonX.Y 中安装 Python X.Y 库。假设该目录包含一个子目录 /usr/local/lib/pythonX.Y/site-packages,其中包含三个子子目录:foo、bar 和 spam,以及两个路径配置文件:foo.pth 和 bar.pth。假设 foo.pth 包含以下内容:
# foo 包配置
foo
bar
bletch
并且 bar.pth 包含:
# bar 包配置
bar
则下面特定版本目录将以如下顺序被添加到 sys.path:
/usr/local/lib/pythonX.Y/site-packages/bar
/usr/local/lib/pythonX.Y/site-packages/foo
请注意 bletch 已被省略因为它并不存在;bar 目录在 foo 目录之前因为 bar.pth 按字母顺序排在 foo.pth 之前;而 spam 已被省略因为它在两个路径配置文件中都未被提及。
让我们假设还有一个 foo.start 文件包含以下内容:
# foo 包启动代码
foo.submod:initialize
现在,当 sys.path 像上面那样扩展之后,并在 Python 将控制权交给用户代码之前,foo.submod 模块将被导入且该模块的 initialize() 函数将被调用。
将 .pth 文件中的 import 行迁移至 .start 文件¶
如果你的包目前带有 name.pth 文件,你可以保持所有 sys.path 扩展行不变。 只有 import 行需要迁移。
要执行迁移,请在您的包中一个可导入模块内创建一个可调用函数(不接受任何参数)。在对应的 name.start 文件中,将其作为 pkg.mod:callable 入口点进行引用。将 import 行中第一个分号之后的所有内容移至 callable() 函数中。
如果您的软件包必须同时兼容不支持 PEP 829 的旧版 Python 和支持该功能的较新版本 Python,请将 name.pth 中的 import 行修改为以下格式:
import pkg.mod; pkg.mod.callable()
较旧版本的 Python 会执行这些 import 行,而较新版本的 Python 则会忽略这些行,转而采用 name.start 文件。在跨越期结束后,请从您的 .pth 文件中删除所有 import 行。
sitecustomize¶
完成这些路径操作后,系统会尝试导入一个名为 sitecustomize 的模块;该模块可执行任意站点特定定制操作。通常,系统管理员会在 site-packages 目录中创建该模块。如果此导入操作以 ImportError 或其子类异常形式失败,且该异常的 name 属性等于 'sitecustomize',则会被静默忽略。若 Python 在无法使用输出流的情况下启动(例如 Windows 上的 pythonw.exe;该设置默认用于启动 IDLE),则 sitecustomize 的任何输出尝试都会被忽略。其他任何异常都会导致进程静默失败,且这种失败可能难以察觉。
usercustomize¶
此后,系统会尝试导入一个名为 usercustomize 的模块;如果 ENABLE_USER_SITE 为真,该模块可执行任意用户特定的自定义操作。此文件应创建在用户站点软件包目录中(见下文);除非被 -s 禁用,否则该目录属于 sys.path 的一部分。如果此导入因 ImportError 或其子类异常而失败,且该异常的 name 属性等于 'usercustomize',则系统会静默忽略该异常。
请注意,对于某些非 Unix 系统,sys.prefix 和 sys.exec_prefix 为空,因此会跳过路径操作;不过,仍会尝试导入 sitecustomize 和 usercustomize。
Readline 配置¶
在支持 readline 的系统上,如果 Python 以 交互模式 启动并且不带 -S 选项,则此模块还将导入并配置 rlcompleter 模块。 默认行为是启用 Tab 键补全并使用 ~/.python_history 作为历史保存文件。 要禁用它,请删除(或重载)你的 sitecustomize 或 usercustomize 模块或你的 PYTHONSTARTUP 文件中的 sys.__interactivehook__ 属性。
在 3.4 版本发生变更: rlcompleter 和 history 会被自动激活。
模块内容¶
- site.PREFIXES¶
site-packages 目录的前缀列表。
- site.ENABLE_USER_SITE¶
显示用户 site-packages 目录状态的旗标。
True意味着它被启用并被添加到sys.path。False意味着它按照用户请求被禁用 (通过-s或PYTHONNOUSERSITE)。None意味着它因安全理由(user 或 group id 和 effective id 之间不匹配)或是被管理员所禁用。
- site.USER_SITE¶
运行中的 Python 的用户级 site-packages 的路径。它可以为
None,如果getusersitepackages()尚未被调用的话。默认值在 UNIX 和 macOS 非框架构建版上为~/.local/lib/pythonX.Y[t]/site-packages,在 macOS 框架构建版上为~/Library/Python/X.Y/lib/python/site-packages,而在 Windows 上为%APPDATA%\Python\PythonXY\site-packages。可选的 "t" 表示自由线程构建版。此目录属于 site 目录,这意味着其中的.pth文件将会被处理。
- site.USER_BASE¶
用户级 site-packages 的基准目录的路径。如果尚未调用
getuserbase()则它可以为None。默认值在 Unix 和 macOS 非框架编译版上为~/.local,在 macOS 框架编译版上为~/Library/Python/X.Y,而在 Windows 上则为%APPDATA%\Python。 这个值会被用于计算针对 用户安装方案 的脚本、数据文件、Python 模块等的安装目录。 另请参阅PYTHONUSERBASE。
- site.main()¶
将所有的标准站点专属目录添加到模块搜索路径。这个函数会在导入此模块时被自动调用,除非 Python 解释器启动时附带了
-S旗标。在 3.3 版本发生变更: 这个函数曾会被无条件调用。
- site.makepath(*paths)¶
使用
os.path.join()将 paths 进行拼接,尝试通过os.path.abspath()使结果变为绝对路径,然后返回一个包含绝对路径及其经os.path.normcase()生成的大小写规范化形式的 2-元组。如果os.path.abspath()抛出OSError,则拼接后的路径将原样用于大小写规范化步骤。返回的元组中的第二个元素是
site模块中用于在不区分大小写的文件系统中比较路径的格式;该元素用于填充known_paths集合,从而防止本模块内各种 API 中出现重复的sys.path条目。
- class site.StartupState(known_paths=None)¶
此类实例会从一个或多个站点目录中累积解释器的启动配置数据。它们是跨多个站点目录批量处理
.pth和.start文件的首选接口,从而确保在任何启动代码运行之前,每个sys.path扩展都能被识别。可选参数 known_paths 是一个经过大小写规范化处理的路径集合(可由
makepath()生成),用于防止重复的sys.path条目。当使用None(默认值)时,该集合由当前的sys.path构建而成;main()则隐式使用此类的某个实例。典型用途:
state = site.StartupState() for sitedir in site_dirs: state.addsitedir(sitedir) state.process()
在 3.15 版本加入.
- addsitedir(sitedir)¶
在 sitedir 中读取
.pth和.start文件,并记录其sys.path扩展名、已弃用的.pth和import行,以及此状态下的.start入口点。所记录的数据在调用process()之前不会生效。
- addsitepackages(prefixes=None)¶
添加由 prefixes 或当 prefixes 为
None时由全局PREFIXES计算得出的全局站点包目录。每个目录的启动数据会被汇总,以便后续由process()进行处理。
- process()¶
通过先将路径扩展添加到
sys.path中,然后执行.start文件入口点以及.pth文件的import行(deprecated),来应用累积状态。该方法不具有幂等性,因此不得在同一个实例上多次调用。否则,累积状态将被多次应用,导致入口点和
import语句被重新执行。
- site.addsitedir(sitedir, known_paths=None)¶
将目录添加到 sys.path 中,并解析在该目录中找到的
.pth和.start文件。通常用于sitecustomize或usercustomize(见上文)。known_paths 参数是一个可选的、经过大小写规范化处理的路径集合,用于防止重复的
sys.path条目。当使用None(默认值)时,该集合会根据当前的sys.path构建而成。对于跨多个站点目录的批处理操作,应显式构建一个
StartupState,并在其上调用StartupState.addsitedir();这样可将.pth和.start的处理延迟到单次StartupState.process()调用之后,从而确保在任何启动代码运行之前,每个sys.path扩展都已可见。在 3.15 版本发生变更: 还会处理
.start文件。 参见 Startup entry points (.start files)。
- site.getsitepackages(prefixes=None)¶
返回包含所有全局 site-packages 目录的列表。
对于 prefixes 中给出的每个目录(或者当 prefixes 为
None时为PREFIXES),该函数将根据系统环境计算其 site-packages 子目录,并返回完整路径列表,不会检查这些路径是否存在。在 3.2 版本加入.
在 3.3 版本发生变更: 添加了可选的 prefixes 形参。
- site.getuserbase()¶
返回用户基准目录的路径
USER_BASE。如果它尚未被初始化,则此函数还将参照PYTHONUSERBASE来设置它。在 3.2 版本加入.
- site.getusersitepackages()¶
返回用户专属 site-packages 目录的路径
USER_SITE。如果它尚未被初始化,则此函数还将参照USER_BASE来设置它。要确定用户专属 site-packages 是否已被添加到sys.path则应当使用ENABLE_USER_SITE.在 3.2 版本加入.
命令行接口¶
site 模块还提供了一个从命令行获取用户目录的方式:
$ python -m site --user-site
/home/user/.local/lib/python3.11/site-packages
如果它被不带参数地调用,它将在标准输出打印 sys.path 的内容,再打印 USER_BASE 的值以及该目录是否存在,然后打印 USER_SITE 的相应信息,最后打印 ENABLE_USER_SITE 的值。
- --user-base¶
输出用户基准目录的路径。
- --user-site¶
输出用户 site-packages 目录的路径。
如果同时给出了两个选项,则将打印用户基准目录和用户站点信息(总是按此顺序),并以 os.pathsep 分隔。
如果给出了其中一个选项,脚本将退出并返回以下值中的一个:如果用户级 site-packages 目录被启用则为 0,如果它被用户禁用则为 1,如果它因安全理由或被管理员禁用则为 2,如果发生错误则为大于 2 的值。
参见
PEP 370 -- 分用户的 site-packages 目录
PEP 829 -- 启动入口点与
.pth文件中导入行的弃用sys.path 模块搜索路径的初始化 --
sys.path的初始化。