10

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

据我了解,加载 python 时,首先lib/python2.7/site-packages/site.py运行。它遍历PYTHONPATH、搜索lib/python2.7/site.py并导入它。这个文件有一个addsitedir方法,它不仅添加了一个路径sys.path,而且处理*.pth了它上面存在的文件。此时,main()lib/python2.7/site.py已运行,并且addsitedir在站点包和用户站点包上运行。

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

  1. addsitedir运行了lib/python2.7/site-packages两次。
  2. 这本身并没有那么糟糕(没有什么可以添加到 sys.path 两次),但似乎lib/python2.7/site.py有一种机制可以让雄心勃勃的用户sys.path通过实现一个usercustomize模块来进行操作(嘿,它甚至在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这里

4

1 回答 1

9

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

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

  • Python 以有限的sys.path. site-packages不是此列表的一部分,除非您设置了PYTHONPATH包含它的变量。
  • Python 导入site.py,它将导入第一个列在sys.path.
  • lib/python2.7/site.py找到并加载
  • site.py添加site-packagessys.path

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

但是,您的安装安装了较旧的setuptools版本,并且包含一个特殊版本的site.py,如果该命令尚未安装,该easy_install命令将安装到该版本中。site-packages它将site.py通过显式扫描原始文件sys.path并忽略任何PYTHONPATH提供的路径并使用和低级函数手动加载原始模块来加载原始文件,从而绕过正常的模块缓存。site.pyimp.find_module()imp.load_module()

它的目的是改变sys.path顺序以赋予PYTHONPATH-listed.pth文件更高的优先级,请参阅添加补丁的原始提交

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

早在 2006 年setuptools原始.setuptools

所以,要么你的 Linux 发行版已经设置为添加lib/python2.7/site-packages到你的PYTHONPATH或者你的 shell 已经为你设置了这个,或者你的 Python 已经被修补以包含它,并且setuptoolssite-packages.

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

于 2014-09-25T09:47:29.600 回答