18.2. site — 整站范围内的配置信息
site
模块处理特定于站点的配置,尤其是导入路径。
导入路径
每次解释器启动时都会自动导入 site
。 在导入时,它扩展了 sys.path
,其中特定于站点的名称是通过将前缀值 sys.prefix
和 sys.exec_prefix
与几个后缀组合而构建的。 使用的前缀值保存在模块级变量 PREFIXES
中以供稍后参考。 在 Windows 下,后缀是一个空字符串和 lib/site-packages
。 对于类 Unix 平台,值为 lib/python$version/site-packages
(其中 $version
由解释器的主要版本号和次要版本号替换,例如 3.5
)和 lib/site-python
。
site_import_path.py
import sys
import os
import site
if 'Windows' in sys.platform:
SUFFIXES = [
'',
'lib/site-packages',
]
else:
SUFFIXES = [
'lib/python{}/site-packages'.format(sys.version[:3]),
'lib/site-python',
]
print('Path prefixes:')
for p in site.PREFIXES:
print(' ', p)
for prefix in sorted(set(site.PREFIXES)):
print()
print(prefix)
for suffix in SUFFIXES:
print()
print(' ', suffix)
path = os.path.join(prefix, suffix).rstrip(os.sep)
print(' exists :', os.path.exists(path))
print(' in path:', path in sys.path)
测试组合产生的每个路径,并将那些存在的路径添加到 sys.path
中。 此输出显示安装在 Mac OS X 系统上的 Python 框架版本。
$ python3 site_import_path.py
Path prefixes:
/Library/Frameworks/Python.framework/Versions/3.5
/Library/Frameworks/Python.framework/Versions/3.5
/Library/Frameworks/Python.framework/Versions/3.5
lib/python3.5/site-packages
exists : True
in path: True
lib/site-python
exists : False
in path: False
用户目录
除了全局站点包路径之外, site
还负责将用户特定的位置添加到导入路径。 用户特定的路径都基于 USER_BASE
目录,该目录通常位于当前用户拥有(和可写)的文件系统的一部分中。 在 USER_BASE
目录中是一个 site-packages
目录,其路径可以作为 USER_SITE
访问。
site_user_base.py
import site
print('Base:', site.USER_BASE)
print('Site:', site.USER_SITE)
使用前面描述的相同的特定于平台的后缀值创建 USER_SITE
路径名。
$ python3 site_user_base.py
Base: /Users/dhellmann/.local
Site: /Users/dhellmann/.local/lib/python3.6/site-packages
用户基目录可以通过 PYTHONUSERBASE
环境变量设置,并具有特定于平台的默认值( Windows 的 ~/Python$version/site-packages
和非 Windows 的 ~/.local
)。
$ PYTHONUSERBASE=/tmp/$USER python3 site_user_base.py
Base: /tmp/dhellmann
Site: /tmp/dhellmann/lib/python3.6/site-packages
在某些可能导致安全问题的情况下禁用用户目录(例如,如果进程使用与启动它的实际用户不同的有效用户或组 ID 运行)。 应用程序可以通过检查 ENABLE_USER_SITE
来检查设置。
site_enable_user_site.py
import site
status = {
None: 'Disabled for security',
True: 'Enabled',
False: 'Disabled by command-line option',
}
print('Flag :', site.ENABLE_USER_SITE)
print('Meaning:', status[site.ENABLE_USER_SITE])
也可以在命令行中使用 -s
显式禁用用户目录。
$ python3 site_enable_user_site.py
Flag : True
Meaning: Enabled
$ python3 -s site_enable_user_site.py
Flag : False
Meaning: Disabled by command-line option
路径配置文件
当路径添加到导入路径时,它们也会扫描路径配置文件。 路径配置文件是纯文本文件,扩展名为 .pth
。 文件中的每一行都可以采用四种形式之一。
- 应添加到导入路径的另一个位置的完整路径或相对路径。
- 要执行的 Python 语句。 所有这些行必须以
import
语句开头。 - 空行被忽略。
- 以
#
开头的行被视为注释并被忽略。
路径配置文件可用于扩展导入路径以查找未自动添加的位置。 例如,当使用 python setup.pydevelop
在开发模式下安装包时, setuptools
包添加了一个 easy-install.pth
的路径。
扩展 sys.path
的函数是公共的,它可以在示例程序中用于显示路径配置文件的工作方式。 给定一个名为 with_modules
的目录,其中包含文件 mymodule.py
,其中 print
语句显示了模块的导入方式:
with_modules/mymodule.py
import os
print('Loaded {} from {}'.format(
__name__, __file__[len(os.getcwd()) + 1:])
)
这个脚本显示了 addsitedir()
如何扩展导入路径,以便解释器可以找到所需的模块。
site_addsitedir.py
import site
import os
import sys
script_directory = os.path.dirname(__file__)
module_directory = os.path.join(script_directory, sys.argv[1])
try:
import mymodule
except ImportError as err:
print('Could not import mymodule:', err)
print()
before_len = len(sys.path)
site.addsitedir(module_directory)
print('New paths:')
for p in sys.path[before_len:]:
print(p.replace(os.getcwd(), '.')) # shorten dirname
print()
import mymodule
将包含该模块的目录添加到 sys.path
后,该脚本可以毫无问题地导入 mymodule
。
$ python3 site_addsitedir.py with_modules
Could not import mymodule: No module named 'mymodule'
New paths:
./with_modules
Loaded mymodule from with_modules/mymodule.py
路径由 addsitedir()
改变,不仅仅是将参数附加到 sys.path
。 如果给 addsitedir
的目录包含与模式 *.pth
匹配的任何文件,它们将作为路径配置文件加载。 给定如下目录结构
with_pth
├── pymotw.pth
└── subdir
└── mymodule.py
如果 with_pth/pymotw.pth
包含
# 添加单个子目录到路径
./subdir
然后可以通过添加 with_pth
作为站点目录来导入 with_pth/subdir/mymodule.py
,即使该模块不在该目录中,因为 with_pth
和 with_pth/subdir
都被添加到导入路径中。
$ python3 site_addsitedir.py with_pth
Could not import mymodule: No module named 'mymodule'
New paths:
./with_pth
./with_pth/subdir
Loaded mymodule from with_pth/subdir/mymodule.py
如果站点目录包含多个 .pth
文件,则按字母顺序处理它们。
$ ls -F multiple_pth
a.pth
b.pth
from_a/
from_b/
$ cat multiple_pth/a.pth
./from_a
$ cat multiple_pth/b.pth
./from_b
这种情况下,模块位于 multiple_pth/from_a
中,因为 a.pth
在 b.pth
之前被读取。
$ python3 site_addsitedir.py multiple_pth
Could not import mymodule: No module named 'mymodule'
New paths:
./multiple_pth
./multiple_pth/from_a
./multiple_pth/from_b
Loaded mymodule from multiple_pth/from_a/mymodule.py
自定义站点配置
site
模块还负责在 sitecustomize
模块中加载由本地站点所有者定义的站点范围的定制。 sitecustomize
的用途包括扩展导入路径并启用覆盖,分析或其他开发工具。
例如,这个 sitecustomize.py
脚本使用基于当前平台的目录扩展导入路径。 /opt/python
中特定于平台的路径被添加到导入路径中,因此可以导入安装在那里的任何包。 像这样的系统对于通过共享文件系统在网络上的主机之间共享包含编译的扩展模块的包很有用。 只需要在每个主机上安装 sitecustomize.py
脚本,并且可以从文件服务器访问其他包。
with_sitecustomize/sitecustomize.py
print('Loading sitecustomize.py')
import site
import platform
import os
import sys
path = os.path.join('/opt',
'python',
sys.version[:3],
platform.platform(),
)
print('Adding new path', path)
site.addsitedir(path)
可以使用一个简单的脚本来显示在 Python 开始运行您自己的代码之前导入 sitecustomize.py
。
with_sitecustomize/site_sitecustomize.py
import sys
print('Running main program from\n{}'.format(sys.argv[0]))
print('End of path:', sys.path[-1])
由于 sitecustomize
适用于系统范围的配置,因此应将其安装在默认路径中的某处(通常位于 site-packages
目录中)。 此示例明确设置 PYTHONPATH
以确保拾取模块。
$ PYTHONPATH=with_sitecustomize python3 with_sitecustomize/sit\
e_sitecustomize.py
Loading sitecustomize.py
Adding new path /opt/python/3.6/Darwin-17.4.0-x86_64-i386-64bit
Running main program from
with_sitecustomize/site_sitecustomize.py
End of path: /opt/python/3.6/Darwin-17.4.0-x86_64-i386-64bit
自定义用户配置
与 sitecustomize
类似,每次解释器启动时,usercustomize
模块都可用于设置用户特定的设置。 在 sitecustomize
之后加载 usercustomize
可以覆盖站点范围的自定义。
在运行不同操作系统或版本的多个服务器上共享用户主目录的环境中,标准用户目录机制可能无法用于特定于用户的软件包安装。 在这些情况下,可以使用特定于平台的目录树替代。
with_usercustomize/usercustomize.py
print('Loading usercustomize.py')
import site
import platform
import os
import sys
path = os.path.expanduser(os.path.join('~',
'python',
sys.version[:3],
platform.platform(),
))
print('Adding new path', path)
site.addsitedir(path)
另一个类似于 sitecustomize
的简单脚本可用于显示在 Python 开始运行其他代码之前导入 usercustomize.py
。
with_usercustomize/site_usercustomize.py
import sys
print('Running main program from\n{}'.format(sys.argv[0]))
print('End of path:', sys.path[-1])
由于 usercustomize
是针对用户的特定于用户的配置,因此应将其安装在用户默认路径中的某个位置,而不是安装在站点范围的路径上。 默认的 USER_BASE
目录是一个很好的位置。 此示例明确设置 PYTHONPATH
以确保模块获取。
$ PYTHONPATH=with_usercustomize python3 with_usercustomize/site\
_usercustomize.py
Loading usercustomize.py
Adding new path /Users/dhellmann/python/3.5/Darwin-15.5.0-x86_64\
-i386-64bit
Running main program from
with_usercustomize/site_usercustomize.py
End of path: /Users/dhellmann/python/3.5/Darwin-15.5.0-x86_64\
-i386-64bit
禁用用户站点目录功能时,不会导入 usercustomize
,无论它是位于用户站点目录还是其他位置。
$ PYTHONPATH=with_usercustomize python3 -s with_usercustomize/s\
ite_usercustomize.py
Running main program from
with_usercustomize/site_usercustomize.py
End of path: /Users/dhellmann/Envs/pymotw35/lib/python3.5/site-
packages
禁用站点模块
为了在添加自动导入之前保持与 Python 版本的向后兼容性,解释器接受 -S
选项。
$ python3 -S site_import_path.py
Path prefixes:
/Users/dhellmann/Envs/pymotw36/bin/..
/Users/dhellmann/Envs/pymotw36/bin/..
/Users/dhellmann/Envs/pymotw36/bin/..
lib/python3.6/site-packages
exists : True
in path: False
lib/site-python
exists : False
in path: False
另请参阅
- site 标准库文档
- Modules and Imports -- 描述
sys
中定义的导入路径是如何工作的。- setuptools -- 包装库和安装工具
easy_install
。- Running code at Python startup -- 来自 Ned Batchelder 的帖子讨论了在开始主程序执行之前使 Python 解释器运行自定义初始化代码的方法。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。