翻译进度
6
分块数量
2
参与人数

site — 整站范围内的配置信息

这是一篇社区协同翻译的文章,你可以点击右边区块信息里的『改进』按钮向译者提交改进建议。

site 模块处理特定于站点的配置,尤其是导入路径。

导入路径

每次解释器启动时都会自动导入 site 。 在导入时,它扩展了 sys.path ,其中特定于站点的名称是通过将前缀值 sys.prefixsys.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
alphanow 翻译于 2个月前

用户目录

除了全局站点包路径之外, 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
alphanow 翻译于 2个月前

路径配置文件

当路径添加到导入路径时,它们也会扫描路径配置文件。 路径配置文件是纯文本文件,扩展名为 .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_pthwith_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.pthb.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
alphanow 翻译于 2个月前

自定义站点配置

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
alphanow 翻译于 2个月前

自定义用户配置

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
alphanow 翻译于 2个月前

禁用站点模块

为了在添加自动导入之前保持与 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

另请参阅

alphanow 翻译于 2个月前

本文章首发在 PythonCaff
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

参与译者:2
讨论数量: 0
发起讨论


暂无话题~