Python的sys.path是从哪里初始化的?


111

Python的sys.path是从哪里初始化的?

UPD:Python在引用PYTHONPATH之前添加了一些路径:

    >>> import sys
    >>> from pprint import pprint as p
    >>> p(sys.path)
    ['',
     'C:\\Python25\\lib\\site-packages\\setuptools-0.6c9-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\orbited-0.7.8-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\morbid-0.8.6.1-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\demjson-1.4-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\stomper-0.2.2-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\uuid-1.30-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\stompservice-0.1.0-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\cherrypy-3.0.1-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\pyorbited-0.2.2-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\flup-1.0.1-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\wsgilog-0.1-py2.5.egg',
     'c:\\testdir',
     'C:\\Windows\\system32\\python25.zip',
     'C:\\Python25\\DLLs',
     'C:\\Python25\\lib',
     'C:\\Python25\\lib\\plat-win',
     'C:\\Python25\\lib\\lib-tk',
     'C:\\Python25',
     'C:\\Python25\\lib\\site-packages',
     'C:\\Python25\\lib\\site-packages\\PIL',
     'C:\\Python25\\lib\\site-packages\\win32',
     'C:\\Python25\\lib\\site-packages\\win32\\lib',
     'C:\\Python25\\lib\\site-packages\\Pythonwin']

我的PYTHONPATH是:

    PYTHONPATH=c:\testdir

我想知道PYTHONPATH之前的那些路径来自哪里?

Answers:



77

Python确实努力进行智能设置sys.path。如何设置可能会变得非常 复杂。下面的指南是一个打了折扣的,有点不完全,有些-错,但希望-有用的时候Python会什么的使用会发生什么的职级和文件Python程序员指南初始值sys.pathsys.executablesys.exec_prefix,和sys.prefix正常的 python安装上。

首先,python会尽最大努力根据操作系统告诉它在文件系统上的实际物理位置。如果操作系统只是说“ python”正在运行,它将在$ PATH中找到自己。它解析任何符号链接。完成此操作后,它将找到的可执行文件的路径用作sys.executable,no ifs,ands或buts的值。

接下来,确定用于初始值sys.exec_prefixsys.prefix

如果pyvenv.cfg在与该目录相同的目录中有一个文件, sys.executable或者在一个目录中,则python会查看该文件。不同的操作系统对此文件执行不同的操作。

python在此配置文件中查找的值之一是configuration选项home = <DIRECTORY>sys.executable 当它动态设置以后的初始值时,Python将使用此目录而不是包含的目录sys.prefix。如果该applocal = true设置出现在pyvenv.cfgWindows 的 文件中,但没有出现在home = <DIRECTORY>设置中,sys.prefix则将被设置为包含的目录sys.executable

接下来,PYTHONHOME检查环境变量。在Linux和Mac上, sys.prefixsys.exec_prefix设置为PYTHONHOME环境变量,如果它存在,并取代任何home = <DIRECTORY>的设置pyvenv.cfg。在Windows上, sys.prefix并且sys.exec_prefix设置为PYTHONHOME环境变量(如果存在),除非在中存在home = <DIRECTORY>设置,否则将使用该设置pyvenv.cfg

否则,可以通过从或指定的目录(如果有)的位置向后走来找到sys.prefix和。sys.exec_prefixsys.executablehomepyvenv.cfg

如果lib/python<version>/dyn-load在该目录或其任何父目录中找到该文件,则将该目录设置为 sys.exec_prefix在Linux或Mac上。如果lib/python<version>/os.py在目录或其任何子目录中找到该文件 ,则将该目录设置为sys.prefix在Linux,Mac和Windows上,并sys.exec_prefix设置为与Windows 相同的值 sys.prefix。如果applocal = true已设置,则在Windows上将跳过整个步骤 。使用的目录,sys.executable或者如果home设置了目录,则将其pyvenv.cfg用于的初始值sys.prefix

如果找不到或没有找到这些“地标”文件sys.prefix,则python设置sys.prefix为“后备”值。Linux和Mac,例如,使用预编译的缺省值的数值sys.prefixsys.exec_prefix。Windows等到sys.path完全确定要为设置后备值 为止sys.prefix

然后,(您一直在等待)python确定要包含在中的初始值sys.path

  1. python正在执行的脚本目录被添加到sys.path。在Windows上,这始终是空字符串,它告诉python使用脚本所在的完整路径。
  2. 除非您在Windows上并且在中设置为true sys.path否则将添加PYTHONPATH环境变量的内容(如果applocal已设置)pyvenv.cfg
  3. <prefix>/lib/python35.zipLinux / Mac和os.path.join(os.dirname(sys.executable), "python.zip")Windows 上 的zip文件路径已添加到中sys.path
  4. 如果在Windows上没有applocal = true在中设置No pyvenv.cfg,则HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\添加注册表项的子项的内容( 如果有)。
  5. 如果在Windows上未applocal = true在中设置No pyvenv.cfg,并且sys.prefix找不到,则添加注册表项的核心内容HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\如果存在);
  6. 如果在Windows上没有applocal = true在中设置No pyvenv.cfg,则HK_LOCAL_MACHINE\Software\Python\PythonCore\<DLLVersion>\PythonPath\添加注册表项的子项的内容( 如果有)。
  7. 如果在Windows上未applocal = true在中设置No pyvenv.cfg,并且sys.prefix找不到,则添加注册表项的核心内容HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\如果存在);
  8. 如果在Windows上并且未设置PYTHONPATH,则找不到前缀,并且不存在注册表项,则添加PYTHONPATH的相对编译时值;否则,将忽略此步骤。
  9. 相对于dynamic-found添加了编译时宏PYTHONPATH中的路径sys.prefix
  10. 在Mac和Linux上,将sys.exec_prefix添加的值。在Windows上,添加了用于(或将要使用)动态搜索的目录sys.prefix

在Windows的现阶段,如果未找到前缀,则python将尝试通过搜索所有目录中sys.path的地标文件来确定它,就像它尝试使用sys.executable以前的目录一样,直到找到了东西。如果不是,sys.prefix则留空。

最后,在完成所有这些之后,Python加载了site模块,这进一步为sys.path以下模块添加了一些内容:

它从头和尾部分开始最多构建四个目录。头部使用sys.prefixsys.exec_prefix; 空头被跳过。对于尾部,它使用空字符串,然后lib/site-packages(在Windows上)或lib/pythonX.Y/site-packages (然后lib/site-python在Unix和Macintosh上)使用。对于每个不同的首尾组合,它会查看它是否指向现有目录,如果是,则将其添加到sys.path中,并检查新添加的配置文件路径。


1
尽管它的文档说了什么,但sys.executable可以是一个符号链接,或者实际上可以是任何argv[0]包含斜线的内容。没有使用可执行文件的实际路径(来自execv(path, argv)调用)。
jfs

1
关于sys.path在Windows 10上的第一点:我总是以sys.path [0](不是cwd”)获取脚本目录的完整路径。您应该能够执行python some\other\path\than\cwd\main.py
ford04

我同意@ ford04。第一点是不正确的:在Windows上,脚本的目录已添加到sys.path,而不是空白路径,也不添加到cwd。这是在各种Python 3.x安装中。
gwideman

1
哇,太棒了!在绊倒这个真相之前,我还看到了大约10个其他问题和答案,即使您谦虚地承认您还没有全部拥有。
迈克·威廉姆森

1
我将在site-packageshave .pth.egg-link后缀中添加相关文件。
florisla
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.