Python的sys.path从哪里初始化?
Python的sys.path是从哪里初始化的呢?
更新: 在提到PYTHONPATH之前,Python会先添加一些路径:
>>> 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之前的那些路径是从哪里来的?
2 个回答
编辑
我在2015年写这段内容时,关于这个主题没有任何文档。现在根据评论的说法,已经有了,如果你想了解更多,可以去看看。此外,在代码库的getpath.py
文件的评论中,还有一段文字说明这个算法。我仍然认为我的回答是相关的,并且相对较新。
原文如下
Python非常努力地智能设置sys.path
。它的设置方式可能会变得非常 复杂。以下指南是一个简化版,虽然有些不完整和不准确,但希望对普通的Python程序员有用,帮助他们理解Python在正常安装时如何确定sys.path
、sys.executable
、sys.exec_prefix
和sys.prefix
的初始值。
首先,Python会尽力根据操作系统告诉它的信息,找出自己在文件系统中的实际位置。如果操作系统只说“python”正在运行,它会在$PATH中查找。它会解析任何符号链接。一旦完成,它找到的可执行文件的路径就会作为sys.executable
的值,绝对没有其他条件。
接下来,它会确定sys.exec_prefix
和sys.prefix
的初始值。
如果在sys.executable
所在的目录或上一级目录中有一个叫pyvenv.cfg
的文件,Python会查看它。不同的操作系统对这个文件的处理方式不同。
Python在这个配置文件中查找的一个值是配置选项home = <DIRECTORY>
。Python会在动态设置sys.prefix
的初始值时使用这个目录,而不是包含sys.executable
的目录。如果在Windows的pyvenv.cfg
文件中出现了applocal = true
的设置,但没有home = <DIRECTORY>
的设置,那么sys.prefix
将被设置为包含sys.executable
的目录。
接下来,Python会检查PYTHONHOME
环境变量。在Linux和Mac上,如果存在PYTHONHOME
环境变量,sys.prefix
和sys.exec_prefix
会被设置为这个环境变量的值,覆盖pyvenv.cfg
中的任何home = <DIRECTORY>
设置。在Windows上,如果存在PYTHONHOME
环境变量,sys.prefix
和sys.exec_prefix
也会被设置为这个环境变量的值,除非在pyvenv.cfg
中存在home = <DIRECTORY>
的设置,这时会使用后者。
否则,sys.prefix
和sys.exec_prefix
的值会通过从sys.executable
的位置向上查找,或者使用pyvenv.cfg
中给出的home
目录来找到。
如果在该目录或其任何父目录中找到了lib/python<version>/dyn-load
文件,那么该目录会被设置为Linux或Mac上的sys.exec_prefix
。如果在该目录或其任何子目录中找到了lib/python<version>/os.py
文件,那么该目录会被设置为Linux、Mac和Windows上的sys.prefix
,并且在Windows上sys.exec_prefix
会与sys.prefix
相同。如果在Windows上设置了applocal = true
,则会跳过这一步。此时会使用sys.executable
的目录,或者如果在pyvenv.cfg
中设置了home
,则使用该值作为sys.prefix
的初始值。
如果找不到这些“标志”文件,或者sys.prefix
还没有找到,那么Python会将sys.prefix
设置为一个“后备”值。例如,Linux和Mac会使用预编译的默认值作为sys.prefix
和sys.exec_prefix
的值。Windows会等到sys.path
完全确定后,再为sys.prefix
设置后备值。
然后,(大家期待的时刻来了,) Python会确定sys.path
中要包含的初始值。
- 执行的脚本所在的目录会被添加到
sys.path
中。在Windows上,这始终是空字符串,这意味着Python会使用脚本所在的完整路径。 - 如果设置了
PYTHONPATH
环境变量,它的内容会被添加到sys.path
中,除非你在Windows上,并且在pyvenv.cfg
中设置了applocal
为true。 - 压缩文件路径会被添加到
sys.path
中,在Linux/Mac上是<prefix>/lib/python35.zip
,在Windows上是os.path.join(os.dirname(sys.executable), "python.zip")
。 - 如果在Windows上,并且在
pyvenv.cfg
中没有设置applocal = true
,那么注册表键HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\
的子键内容会被添加,如果有的话。 - 如果在Windows上,并且在
pyvenv.cfg
中没有设置applocal = true
,并且sys.prefix
无法找到,那么注册表键HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\
的核心内容会被添加,如果存在的话。 - 如果在Windows上,并且在
pyvenv.cfg
中没有设置applocal = true
,那么注册表键HK_LOCAL_MACHINE\Software\Python\PythonCore\<DLLVersion>\PythonPath\
的子键内容会被添加,如果有的话。 - 如果在Windows上,并且在
pyvenv.cfg
中没有设置applocal = true
,并且sys.prefix
无法找到,那么注册表键HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\
的核心内容会被添加,如果存在的话。 - 如果在Windows上,并且没有设置
PYTHONPATH
,没有找到前缀,并且没有注册表键,那么会添加相对的编译时值的PYTHONPATH
;否则,这一步会被忽略。 - 编译时宏
PYTHONPATH
中的路径会相对于动态找到的sys.prefix
添加。 - 在Mac和Linux上,
sys.exec_prefix
的值会被添加。在Windows上,会添加用于动态查找sys.prefix
的目录(或本来会用到的目录)。
在这个阶段,如果在Windows上没有找到前缀,Python会尝试通过搜索sys.path
中的所有目录来确定它,寻找标志文件,就像之前在sys.executable
的目录中尝试的那样,直到找到为止。如果找不到,sys.prefix
将保持为空。
最后,在这一切之后,Python会加载site
模块,这会进一步向sys.path
添加内容:
它开始从头部和尾部部分构建最多四个目录。头部部分使用
sys.prefix
和sys.exec_prefix
;空的头部会被跳过。尾部部分使用空字符串,然后是lib/site-packages
(在Windows上)或lib/pythonX.Y/site-packages
,然后是lib/site-python
(在Unix和Macintosh上)。对于每个不同的头尾组合,它会检查是否指向一个存在的目录,如果是,就将其添加到sys.path
,并检查新添加的路径是否有配置文件。
编辑:自2021年12月以来,已经没有getpathp.c
(在复杂一词开头的链接),因为实现已经移植到Python中:getpath.py
“从环境变量 PYTHONPATH 初始化,并加上一个依赖于安装的默认值。”