Python中sys.executable和sys.version之间不匹配

Pio*_*ost 9 python linux sudo env

安装了两个Python解释器:

[user@localhost ~]$ /usr/bin/python -V && /usr/local/bin/python -V
Python 2.4.3
Python 2.7.6
Run Code Online (Sandbox Code Playgroud)

PATH它运行的每个命令的Sudo更改如下:

[user@localhost ~]$ env | grep PATH && sudo env | grep PATH
PATH=/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/user/bin
PATH=/usr/bin:/bin
Run Code Online (Sandbox Code Playgroud)

我运行一个测试脚本:

[user@localhost ~]$ cat what_python.py
#!/usr/bin/env python

import sys
print sys.executable
print sys.version
[user@localhost ~]$ sudo python what_python.py
/usr/bin/python
2.7.6 (default, Feb 27 2014, 17:05:07) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-54)]
Run Code Online (Sandbox Code Playgroud)

并获取Python 2.4.3 in sys.executable和2.7.6版中的路径sys.version.显然sys.executable,sys.version不匹配.考虑到sudo如何修改PATH,我可以理解它的价值sys.executable.但是,为什么sys.version报告版本2.7.6而不是版本2.4.3,它会匹配usr/bin/python报告的路径sys.executable

这是我的问题的后续事件Sudo更改PATH,但执行相同的二进制文件

Pio*_*ost 6

两个都是@Graeme

python可能无法检索到这一事实表明它正在进行自己的PATH搜索(...)

和@twalberg

(...)看起来sys.executable搜索当前的PATH而不是解析argv [0](或者因为argv [0]在这种情况下是简单的python ...),(...)

基本上是对的.我不愿意相信Python做的事情如此简单(愚蠢?)就像PATH用来定位自己一样,但事实确实如此.

Python的sys模块在Python/sysmodule.c文件中实现.从版本2.7.6开始,sys.executable在第1422行设置如下:

 SET_SYS_FROM_STRING("executable",
                     PyString_FromString(Py_GetProgramFullPath()));
Run Code Online (Sandbox Code Playgroud)

Py_GetProgramFullPath()函数在文件中定义,Modules/getpath.c从第701行开始:

char *
Py_GetProgramFullPath(void)
{
    if (!module_search_path)
        calculate_path();
    return progpath;
}
Run Code Online (Sandbox Code Playgroud)

函数calcuate_path()在同一文件中定义,并包含以下注释:

/* If there is no slash in the argv0 path, then we have to
 * assume python is on the user's $PATH, since there's no
 * other way to find a directory to start the search from.  If
 * $PATH isn't exported, you lose.
 */
Run Code Online (Sandbox Code Playgroud)

从我的情况可以看出,当导出的第一个Python $PATH与正在运行的Python不同时,也会丢失.

关于计算解释的可执行的位置的过程的更多信息可以在找到顶部getpath.c文件:

在完成任何搜索之前,确定可执行文件的位置.如果argv [0]中有一个或多个斜杠,则不加改变地使用它.否则,必须从shell的路径调用它,因此我们在$ PATH中搜索命名的可执行文件并使用它.如果在$ PATH上找不到可执行文件(或者没有$ PATH环境变量),则使用原始的argv [0]字符串.

接下来,检查可执行位置以查看它是否是符号链接.如果是,则追踪链接(正确解释相对路径名,如果找到),并使用链接目标的目录.

让我们做几个测试来验证上述内容:

如果argv [0]中有一个或多个斜杠,则不加改变地使用它.

[user@localhost ~]$ sudo /usr/local/bin/python what_python.py
/usr/local/bin/python
2.7.6 (default, Feb 27 2014, 17:05:07) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-54)]
Run Code Online (Sandbox Code Playgroud)

好.

如果在$ PATH上找不到可执行文件(或者没有$ PATH环境变量),则使用原始的argv [0]字符串.

[user@localhost ~]$ sudo PATH= python what_python.py
<empty line>
2.7.6 (default, Feb 27 2014, 17:05:07) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-54)]
Run Code Online (Sandbox Code Playgroud)

错误.在这种情况下,sys模块文档中的语句为真 - 如果Python无法检索其可执行文件的实际路径,则sys.executable将为空字符串或None..

让我们看看是否将python的二进制文件的位置添加回PATH(在sudo删除它之后)修复了问题:

[user@localhost ~]$ sudo PATH=$PATH python what_python.py
/usr/local/bin/python
2.7.6 (default, Feb 27 2014, 17:05:07) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-54)]
Run Code Online (Sandbox Code Playgroud)

确实如此.

有关:

  • Python issue 7774 - sys.executable:如果修改了zeroth命令参数,则位置错误.
  • Python问题10835 - sys.executable默认和altinstall
  • python-dev邮件列表线程 - 朝着更严格的sys.executable定义
  • Stackoverflow 问题 - 如何在C中查找可执行文件的位置