Python是如何设置sys.path的?它是在什么时候设置的?(涉及IT技术)

86
抱歉,我只能使用英文回答您的问题。
import sys 
print sys.path

在我的Mac上(Mac OS X 10.6.5,Python 2.6.1),我得到以下结果。

/Library/Python/2.6/site-packages/ply-3.3-py2.6.egg
...
/Library/Python/2.6/site-packages/ipython-0.10.1-py2.6.egg
/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python26.zip
/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6
/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-darwin
/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-mac
/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-mac/lib-scriptpackages
/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python /System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-tk /System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-old /System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-dynload /Library/Python/2.6/site-packages /System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC /System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/wx-2.8-mac-unicode

它们被分成了5类:

  • /Library/Python/2.6/site-packages/*.egg
  • /Library/Python/2.6/site-packages
  • Frameworks/Python.framework/Versions/2.6/lib/python2.6
  • Frameworks/Python.framework/Versions/2.6/Extras/lib/python
  • 从PYTHONPATH环境变量中得到的路径。

我可以使用以下代码添加更多路径:

sys.path.insert(0, MORE_PATH)
  • 是哪些例程设置了这些路径,何时设置?
  • 是否有一些路径是在Python源代码中构建的?
  • 插入 'sys.path.insert' 的路径是否有可能被忽略?我很好奇,因为使用mod_wsgi时,我发现这些路径用 'sys.path.insert' 找不到。我在 另一个帖子 中提出了这个问题。

补充

根据Michael的回答,我查看了site.py文件,并得到以下代码。

def addsitepackages(known_paths):
    """Add site-packages (and possibly site-python) to sys.path"""
    sitedirs = []
    seen = []

    for prefix in PREFIXES:
        if not prefix or prefix in seen:
            continue
        seen.append(prefix)

        if sys.platform in ('os2emx', 'riscos'):
            sitedirs.append(os.path.join(prefix, "Lib", "site-packages"))
        elif sys.platform == 'darwin' and prefix == sys.prefix:
            sitedirs.append(os.path.join("/Library/Python", sys.version[:3], "site-packages"))

我也认为具有site.py的目录名称(/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6 对于我的Mac)应该嵌入Python源代码中。


2
这个问题的一部分可以通过查看Python的sys.path值来回答吗? - wkl
如果你仍在尝试解决之前的问题 - 很可能你的问题在于启动文件,而不是与网站导入有关的问题。对于一个软件包来说,删除它们不知道的路径是极其不好的做法。 - nate c
为什么 seen 不是一个集合? :P - Mr_and_Mrs_D
我找到的对于同样问题最好的答案可以在这里找到,这是一个指向另一个SO问题的答案链接。 - Mike Williamson
7个回答

34

大部分配置都在 Python 的 site.py 文件中设置,当解释器启动时(除非使用 -S 选项启动),该文件会被自动导入。在解释器初始化期间,一些路径会在解释器本身中进行设置(你可以通过使用 -S 选项启动 Python 来查看这些路径)。

此外,一些框架(例如 Django)在启动时修改 sys.path 以满足其要求。

site 模块拥有相当好的文档,还有注释过的源代码。如果你通过 python -m site 命令来运行它,它还会打印一些信息。


显然,在Debian及其衍生版中,目录/usr/local/lib/python<version>/dist-packages/usr/{lib,share}/python<version>/dist-packages会自动添加到路径中(根据Ubuntu 14.04中的/usr/lib/python2.7/site.py文件)。 - z0r

16

来自学习Python

sys.path是模块搜索路径。Python在程序启动时自动配置它,将顶层文件的主目录(或空字符串以指定当前工作目录)、任何PYTHONPATH目录、您创建的任何.em pth文件路径的内容以及标准库目录合并在一起。结果是一个目录名称字符串列表,Python 在每次导入新文件时搜索其中的目录。


6

site.py确实是答案。我想要消除在我的mac上默认安装的旧Python的任何依赖关系。这很有效,因为每次启动python解释器时都会调用'site.py'。

对于Mac,我在/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/site.py的main()末尾手动添加了以下行:

    sys.path =  filter (lambda a: not a.startswith('/System'), sys.path)

请注意,在运行Python时,使用命令行选项-S可以防止site.py模块的运行。来自文档 - 禁用模块 site 的导入以及它所涉及的sys.path的站点相关操作. - Piotr Dobrogost

4

路径有以下几个部分:

  • 操作系统库所在的路径
  • Python启动时的当前目录
  • $PYTHONPATH 环境变量
  • 可以在运行时添加路径。

路径不会被忽略,但是可能无法找到并且不会引发错误。应该只添加到sys.path中,而不是从中删除。Django 不会删除路径。


1
除接受的答案外,针对评论中说模块不应该从sys.path中移除条目的问题,需要做出说明:
这基本上是正确的,但有时你可能确实希望通过删除条目来修改sys.path。举一个例子,这是针对Mac特定情况下的;类似的*nix / Windows也可能存在 - 如果您创建了一个自定义的 Python.framework 以包含到您自己的项目中,您可能希望忽略指向系统 Python.framework 的默认sys.path 条目。
你有几个选择:
  1. 像@damirv所建议的那样黑客修改site.py,或者
  2. 添加一个自定义框架中的自己的sitecustomize模块(或包),以达到相同的效果。 如site.py注释所示(至少针对2.7.6):

    在这些路径操作之后,会尝试导入一个名为sitecustomize的模块, 它可以执行任意其他与站点相关的自定义。如果此导入使用 ImportError异常失败,则它将被静默忽略。


1
请注意:如果设置了PYTHONHOME环境变量,则标准库将从该路径加载,而不是默认路径,如文档所述
这并不是对问题的直接回答,但我刚刚发现了一个导致错误的标准库被加载的问题,我的搜索结果带我来到这里。

在mod_wsgi的情况下,PYTHONHOME并不适用,因为Apache不会从用户环境启动,并且它从系统单元脚本启动的根用户也不会设置它。 - Graham Dumpleton
1
@GrahamDumpleton 或许吧,但问题标题可能会在这里引导其他更一般的情况。我只是希望这些信息能对某些人有所帮助。 - Gilly

1
你正在使用系统自带的python /usr/bin/python
在python启动时,sys.path是从系统文件中设置的。
不要触碰那些文件,特别是site.py,因为这可能会干扰系统。
但是,你可以在python中更改sys.path,尤其是在启动时:
在~/.bashrc或~/.zshrc中: export PYTHONSTARTUP=~/.pythonrc 在~/.pythonrc中:
写入你对sys.path的更改。
这些更改仅适用于你的交互式shell。
为了在系统风险较小的情况下进行编程,安装你自己的最新版本的python。

你如何判断“你正在使用系统Python /usr/bin/python。”? - Acton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接