Python中sys.executable和sys.version之间不匹配
安装了两个Python解释器: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
[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)]