python:lib/site-packages/site.py和lib/site.py之间的相互作用

Kor*_*rem 9 python linux sys.path python-2.7

由于我设法解决的一个特定问题,我今天花了大部分时间来弄清楚site.py是如何工作的.有一点我不明白.

据我所知,当加载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模块进行操作(嘿,它甚至在文档中).显然,当您实现这样的机制时,您希望确保用户最后进入,这样他就可以控制添加的所有内容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
Run Code Online (Sandbox Code Playgroud)

那我在这问什么呢?:)

答:我很欣赏为什么需要第二次调用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
>>> 
Run Code Online (Sandbox Code Playgroud)

输出python -vv这里

Mar*_*ers 9

lib/python2.7/site-packages/site.py文件未正常加载.这是因为它lib/python2.7/site.py的添加作业site-packages为路径sys.path,首先,与site.pysite-packages根本不可见.如果你有一个site.pyin site-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.py模块,从而绕过正常的模块缓存.imp.find_module()imp.load_module()

它的目的是改变sys.path命令,使PYTHONPATH列出的.pth文件具有更高的优先级,请参阅添加补丁原始提交:

注意:此版本包含一个被黑客攻击的"site.py",用于支持在sys.path上的site-packages 之前的目录中处理.pth文件.

这个补丁已经完全从最近的setuptools版本中删除了,早在2006年setuptools就已经删除.

因此,您的Linux发行版已经设置为添加lib/python2.7/site-packages到您PYTHONPATH或您的shell已经为您设置了这个,或者您的Python已经修补以包含它,并且您的旧版setuptools"补丁"已经存在site-packages.

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