【问题标题】:python: Interplay between lib/site-packages/site.py and lib/site.pypython:lib/site-packages/site.py 和 lib/site.py 之间的相互作用
【发布时间】:2014-11-01 03:05:07
【问题描述】:

由于我设法解决了一个特定的problem,我今天大部分时间都在弄清楚 site.py(s) 是如何工作的。有一点不明白。

据我了解,加载 python 时,首先运行lib/python2.7/site-packages/site.py。它遍历PYTHONPATH,搜索lib/python2.7/site.py,然后导入它。该文件具有addsitedir 方法,不仅添加了sys.path 的路径,还处理了存在于其上的*.pth 文件。此时,lib/python2.7/site.py 中的 main() 运行,addsitedir 在站点包和用户站点包上运行。

现在是奇怪的部分。现在我们回到lib/python2.7/site-packages/site.py,它遍历pythonpath中的每条路径,并在上面运行addsitedir。我觉得这很奇怪,原因有两个:

  1. addsitedirlib/python2.7/site-packages 上运行了两次。
  2. 这本身并没有那么糟糕(没有什么可以添加到 sys.path 两次),但似乎lib/python2.7/site.py 具有允许雄心勃勃的用户通过实现usercustomize 模块来操纵sys.path 的机制(嘿,它甚至在docs)。显然,当您实施这样的机制时,您希望确保用户最后进入,以便他可以控制添加到sys.path 的所有内容。但这不是这里的情况(因为我很沮丧地发现)。最有可能的是,第二次调用 lib/python2.7/site-packages 将覆盖在 usercustomize 中完成的所有操作。

我知道这很糟糕,但我向addsitedir 添加了一个打印语句,打印它接收到的路径,这样我就可以显示发生了什么。这些是处理的路径:

/home/user/.local/lib/python2.7/site-packages #lib/python2.7/site.py
/home/user/py/lib/python2.7/site-packages     #lib/python2.7/site.py
#This is where your usercustomize runs
#Followin calls are from lib/python2.7/site-packages/site.py
/home/user/py/lib/python2.7/site-packages/numpy-1.9.0-py2.7-linux-x86_64.egg
/home/user/Develop/Python/myproject
/home/user/lmfit-0.7.2
/home/user/py/lib/python2.7/site-packages #NOTE: this runs a second time

那我在这里问什么? :)

A.对于为什么需要第二次调用 site-packages 的见解,我将不胜感激。

B. usercustomize 是否确实受到限制,因为我认为这是由于这种实现?考虑到这一点,您将如何实现从 sys.path(理论上)删除路径?


请求的调试输出:

:genie39:~ ;-) python2.7 -v
# installing zipimport hook
import zipimport # builtin
# installed zipimport hook
# /home/user/py/lib/python2.7/site-packages/site.pyc matches /home/user/py/lib/python2.7/site-packages/site.py
import site # precompiled from /home/user/py/lib/python2.7/site-packages/site.pyc
# /home/user/py/lib/python2.7/os.pyc matches /home/user/py/lib/python2.7/os.py
import os # precompiled from /home/user/py/lib/python2.7/os.pyc
import errno # builtin
import posix # builtin
# /home/user/py/lib/python2.7/posixpath.pyc matches /home/user/py/lib/python2.7/posixpath.py
import posixpath # precompiled from /home/user/py/lib/python2.7/posixpath.pyc
# /home/user/py/lib/python2.7/stat.pyc matches /home/user/py/lib/python2.7/stat.py
import stat # precompiled from /home/user/py/lib/python2.7/stat.pyc
# /home/user/py/lib/python2.7/genericpath.pyc matches /home/user/py/lib/python2.7/genericpath.py
import genericpath # precompiled from /home/user/py/lib/python2.7/genericpath.pyc
# /home/user/py/lib/python2.7/warnings.pyc matches /home/user/py/lib/python2.7/warnings.py
import warnings # precompiled from /home/user/py/lib/python2.7/warnings.pyc
# /home/user/py/lib/python2.7/linecache.pyc matches /home/user/py/lib/python2.7/linecache.py
import linecache # precompiled from /home/user/py/lib/python2.7/linecache.pyc
# /home/user/py/lib/python2.7/types.pyc matches /home/user/py/lib/python2.7/types.py
import types # precompiled from /home/user/py/lib/python2.7/types.pyc
# /home/user/py/lib/python2.7/UserDict.pyc matches /home/user/py/lib/python2.7/UserDict.py
import UserDict # precompiled from /home/user/py/lib/python2.7/UserDict.pyc
# /home/user/py/lib/python2.7/_abcoll.pyc matches /home/user/py/lib/python2.7/_abcoll.py
import _abcoll # precompiled from /home/user/py/lib/python2.7/_abcoll.pyc
# /home/user/py/lib/python2.7/abc.pyc matches /home/user/py/lib/python2.7/abc.py
import abc # precompiled from /home/user/py/lib/python2.7/abc.pyc
# /home/user/py/lib/python2.7/_weakrefset.pyc matches /home/user/py/lib/python2.7/_weakrefset.py
import _weakrefset # precompiled from /home/user/py/lib/python2.7/_weakrefset.pyc
import _weakref # builtin
# /home/user/py/lib/python2.7/copy_reg.pyc matches /home/user/py/lib/python2.7/copy_reg.py
import copy_reg # precompiled from /home/user/py/lib/python2.7/copy_reg.pyc
import imp # builtin
# /home/user/py/lib/python2.7/site.pyc matches /home/user/py/lib/python2.7/site.py
import site # precompiled from /home/user/py/lib/python2.7/site.pyc
# /home/user/py/lib/python2.7/traceback.pyc matches /home/user/py/lib/python2.7/traceback.py
import traceback # precompiled from /home/user/py/lib/python2.7/traceback.pyc
# /home/user/py/lib/python2.7/sysconfig.pyc matches /home/user/py/lib/python2.7/sysconfig.py
import sysconfig # precompiled from /home/user/py/lib/python2.7/sysconfig.pyc
# /home/user/py/lib/python2.7/re.pyc matches /home/user/py/lib/python2.7/re.py
import re # precompiled from /home/user/py/lib/python2.7/re.pyc
# /home/user/py/lib/python2.7/sre_compile.pyc matches /home/user/py/lib/python2.7/sre_compile.py
import sre_compile # precompiled from /home/user/py/lib/python2.7/sre_compile.pyc
import _sre # builtin
# /home/user/py/lib/python2.7/sre_parse.pyc matches /home/user/py/lib/python2.7/sre_parse.py
import sre_parse # precompiled from /home/user/py/lib/python2.7/sre_parse.pyc
# /home/user/py/lib/python2.7/sre_constants.pyc matches /home/user/py/lib/python2.7/sre_constants.py
import sre_constants # precompiled from /home/user/py/lib/python2.7/sre_constants.pyc
# /home/user/py/lib/python2.7/_sysconfigdata.pyc matches /home/user/py/lib/python2.7/_sysconfigdata.py
import _sysconfigdata # precompiled from /home/user/py/lib/python2.7/_sysconfigdata.pyc
# zipimport: found 604 names in /home/user/py/lib/python2.7/site-packages/pytz-2014.7-py2.7.egg
# zipimport: found 20 names in /home/user/py/lib/python2.7/site-packages/hashlib-20081119-py2.7-linux-x86_64.egg
# zipimport: found 40 names in /home/user/py/lib/python2.7/site-packages/pysqlite-2.6.3-py2.7-linux-x86_64.egg
# zipimport: found 7 names in /home/user/py/lib/python2.7/site-packages/mock-1.0.1-py2.7.egg
import encodings # directory /home/user/py/lib/python2.7/encodings
# /home/user/py/lib/python2.7/encodings/__init__.pyc matches /home/user/py/lib/python2.7/encodings/__init__.py
import encodings # precompiled from /home/user/py/lib/python2.7/encodings/__init__.pyc
# /home/user/py/lib/python2.7/codecs.pyc matches /home/user/py/lib/python2.7/codecs.py
import codecs # precompiled from /home/user/py/lib/python2.7/codecs.pyc
import _codecs # builtin
# /home/user/py/lib/python2.7/encodings/aliases.pyc matches /home/user/py/lib/python2.7/encodings/aliases.py
import encodings.aliases # precompiled from /home/user/py/lib/python2.7/encodings/aliases.pyc
# /home/user/py/lib/python2.7/encodings/utf_8.pyc matches /home/user/py/lib/python2.7/encodings/utf_8.py
import encodings.utf_8 # precompiled from /home/user/py/lib/python2.7/encodings/utf_8.pyc
Python 2.7.8 (default, Sep  7 2014, 12:14:33) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
dlopen("/home/user/py/lib/python2.7/site-packages/readline-6.2.4.1-py2.7-linux-x86_64.egg/readline.so", 2);
import readline # dynamically loaded from /home/user/py/lib/python2.7/site-packages/readline-6.2.4.1-py2.7-linux-x86_64.egg/readline.so
>>> 

python -vv 的输出是here

【问题讨论】:

    标签: python linux python-2.7 sys.path


    【解决方案1】:

    lib/python2.7/site-packages/site.py 文件未正常加载。那是因为lib/python2.7/site.py 的工作是将site-packages 路径添加到sys.path 开头,而site-packages 中的site.py 根本不可见。如果您在site-packages 中有site.py,那么这是一个错误,那里应该没有这样的文件。

    没有补丁的 Python 会发生什么:

    • Python 以有限的sys.path 启动。 site-packages 不属于此列表,除非您设置了一个包含它的 PYTHONPATH 变量。
    • Python 导入site.py,它会导入sys.path 上列出的第一个。
    • 找到并加载了lib/python2.7/site.py
    • site.pysite-packages 添加到 sys.path

    就是这样,不再加载site.py 模块。即使您尝试过,它也会找到已经导入的模块; sys.modules['site'] 存在并保存从 lib/python2.7/site.py 加载的对象。

    但是,您的安装安装了较旧的setuptools,它包括一个special version of site.py,如果还没有easy_install 命令will install into site-packages。它将通过显式扫描原始sys.path 来加载原始site.py,忽略任何PYTHONPATH 提供的路径,并使用imp.find_module()imp.load_module() 低级函数loading the original site.py module manually,从而绕过正常的模块缓存.

    它的目的是改变sys.path 的顺序,为PYTHONPATH-listed .pth 文件提供更高的优先级,参见original commit adding the patch

    注意:此版本包含一个被黑的“site.py”以支持处理 .pth 文件位于 sys.path 上 之前 站点包的目录中。

    该补丁已从最近的setuptools 版本as early as 2006 in the original setuptools 中完全删除。

    因此,您的 Linux 发行版已设置为将 lib/python2.7/site-packages 添加到您的 PYTHONPATH,或者您的 shell 已为您设置此设置,或者您的 Python 已修补以包含它, 你的site-packages 中有旧的setuptools“补丁”。

    删除该文件是完全安全的。

    【讨论】:

    • 这个答案是确定的并且非常有帮助。 site-packages/site.py 很可能来自安装 setuptools。将其安装到自定义 Python 安装required setting PYTHONPATH旧方式。但是,easy_install no longer requires that。 “[A]所有这些 [旧方式] 都被 Python 2.6 中 PEP-370 引入的用户方案有效地弃用了。”
    猜你喜欢
    • 1970-01-01
    • 2017-02-19
    • 2017-04-25
    • 2010-12-16
    • 2016-03-28
    • 2022-12-12
    • 1970-01-01
    • 2022-12-30
    • 2012-03-12
    相关资源
    最近更新 更多