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

Python中sys.executable和sys.version之间不匹配,python,linux,sudo,env,Python,Linux,Sudo,Env,安装了两个Python解释器: [user@localhost ~]$ /usr/bin/python -V && /usr/local/bin/python -V Python 2.4.3 Python 2.7.6 Sudo为其运行的每个命令更改路径,如下所示: [user@localhost ~]$ env | grep PATH && sudo env | grep PATH PATH=/usr/kerberos/bin:/usr/local/bin:/u

安装了两个Python解释器:

[user@localhost ~]$ /usr/bin/python -V && /usr/local/bin/python -V
Python 2.4.3
Python 2.7.6
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
我运行一个测试脚本:

[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)]
并在
sys.executable
中获取Python 2.4.3的路径,在
sys.version
中报告版本2.7.6。显然
sys.executable
sys.version
不匹配。考虑到sudo如何修改路径,我可以理解sys.executable的值。但是,为什么
sys.version
报告的是版本2.7.6,而不是版本2.4.3,它将匹配
usr/bin/python
报告的路径
sys.executable


这是我问题的后续

我认为
/usr/local/bin/python
是正在运行的可执行文件。版本字符串几乎可以肯定地编译成了python,因此不太可能出错。查看
sys.executable
的文档:

sys.executable

在有意义的系统上,为Python解释器提供可执行二进制文件的绝对路径的字符串。如果Python无法检索其可执行文件的实际路径,sys.executable将为空字符串或无

python
可能无法检索这一事实表明它正在使用
PATH
sudo设置的
PATH进行自己的
PATH
搜索(根据我对上一个问题的回答,这与它用于查找可执行文件的路径不同)

这里唯一确定的方法是深入研究python实现,但一般来说,版本字符串更可能是您可以信任的字符串。另一方面,
sudo
使用
execve
执行命令(至少根据
man
页面)。您必须指定可执行文件到
execve
的完整路径(一些
exec
变体执行它们自己的
path
搜索,而这一个没有)。因此,对于
python
来说,填写
sys.executable
应该是很容易的事

我不知道是否有任何方法可以为
python
解释器获取实际的
argv[0]
sys.argv[0]
始终是脚本的名称或
-c
),但这将是一个有趣的发现。如果是
/usr/local/bin/python
,这将是
python
中的一个bug

我认为最好的办法就是在
/etc/sudoers
中设置
安全路径
,希望这样你能获得一些一致性

更新 实际上,
execve
接受可执行路径的参数,然后是一个
argv
数组,因此
argv[0]
不一定是
/usr/local/bin/python
。尽管如此,您仍然可以通过制作如下脚本来找到答案:

import time
time.sleep(60)
然后运行它并获取
ps
以提供完整的参数:

sudo python sleep.py &
ps -o args= -C python
另外,为了确保运行的是哪个
python
,您可以执行以下操作:

sudo ls -l /proc/PID/exe
当程序运行时。

Both@Graeme

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

还有@twalberg

(…)它看起来像sys.executable搜索当前路径,而不是 解析argv[0](或者可能是因为argv[0]在这种情况下是简单的python) 案例…,(…)

我们基本上是对的。我不愿意相信Python会做一些如此简单(愚蠢?)的事情,比如使用
PATH
来定位自己,但这是真的

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

 SET_SYS_FROM_STRING("executable",
                     PyString_FromString(Py_GetProgramFullPath()));
Py\u GetProgramFullPath()
函数在文件
Modules/getpath.c
中定义,从第行开始:

函数
calcuate\u path()
在同一文件中定义,包含以下内容:

在我的例子中可以看到,当导出的
$PATH
上的第一个Python与正在运行的Python不同时,也会丢失

有关计算解释器可执行文件位置的过程的更多信息,请参见
getpath.c
文件:

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

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

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

如果argv[0]中有一个或多个斜杠,则会原封不动地使用它

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

是的

相关的:

  • Python问题–sys.executable:如果修改了第零个命令参数,则位置错误
  • Python问题–sys.executable default和altinstall
  • python开发人员邮件列表–对sys.executable进行更严格的定义
  • Stackoverflow–如何在C中找到可执行文件的位置

每次启动python解释器时,shell都会转到/usr/bin/python并执行它(请尝试下一步:python-c“导入操作系统;打印(os.environ[“”])”

那么,正如您自己所看到的那样,
ln-l | grep python
/usr/bin/python是指向python解释器可执行文件的软链接

我所做的是:

  • 安装python的最新版本(请访问python的网站, 下载最后一个代码并
    配置&&make&&make安装
  • 检查th的位置
    char *
    Py_GetProgramFullPath(void)
    {
        if (!module_search_path)
            calculate_path();
        return progpath;
    }
    
    /* 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.
     */
    
    [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)]
    
    [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)]
    
    [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)]