安装了两个Python解释器:
[user@localhost ~]$ /usr/bin/python -V && /usr/local/bin/python -V
Python 2.4.3
Python 2.7.6
Sudo为其运行的每个命令更改PATH
,如下所示:
[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如何修改PATH,我可以理解sys.executable
的价值。但是,为什么sys.version
报告版本2.7.6而不是版本2.4.3,它会匹配usr/bin/python
报告的sys.executable
路径?
答案 0 :(得分:5)
两个@Graeme
python可能无法检索到这一事实表明它 正在进行自己的PATH搜索(...)
和@twalberg
(...)看起来sys.executable搜索当前的PATH而不是 解析argv [0](或者因为argv [0]在这里是简单的python case ...),(...)
基本上是正确的。我不愿意相信Python做的事情如此简单(愚蠢?),而不是使用PATH
来定位自己,但这是真的。
Python的sys
模块在Python/sysmodule.c
文件中实现。从版本2.7.6开始,sys.executable
设置为1422行,如下所示:
SET_SYS_FROM_STRING("executable",
PyString_FromString(Py_GetProgramFullPath()));
Py_GetProgramFullPath()
函数在文件Modules/getpath.c
中定义,从第701行开始:
char *
Py_GetProgramFullPath(void)
{
if (!module_search_path)
calculate_path();
return progpath;
}
函数calcuate_path()
在同一文件中定义,包含以下comment:
/* 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.
*/
从我的情况可以看出,当导出的$PATH
上的第一个Python与正在运行的Python不同时,也会丢失。
有关计算解释程序可执行文件位置的过程的更多信息,请参见getpath.c
[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)]
文件的top:
在完成任何搜索之前,可执行文件的位置是 决心。如果argv [0]中有一个或多个斜杠,则使用它 不变。否则,必须从shell的路径调用它, 所以我们在$ PATH中搜索命名的可执行文件并使用它。如果 在$ PATH上找不到可执行文件(或者没有$ PATH环境 变量),使用原始的argv [0]字符串。
接下来,检查可执行位置以查看它是否是符号 链接。如果是这样,链接被追逐(正确解释一个亲戚 pathname(如果找到)并使用链接目标的目录。
让我们做几个测试来验证上述内容:
如果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)]
确定。
如果在$ PATH上找不到可执行文件(或者没有$ PATH环境变量),则使用原始的argv [0]字符串。
PATH
错误。在这种情况下,来自sys模块的documentation的语句为真 - 如果Python无法检索其可执行文件的真实路径,则sys.executable将为空字符串或None。。
让我们看看是否将python的二进制文件的位置添加回[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)]
(在sudo删除它之后)修复问题:
{{1}}
确实如此。
相关:
答案 1 :(得分:1)
我认为/usr/local/bin/python
是正在运行的可执行文件。版本字符串几乎可以肯定地编译成python
,所以它不太可能出错。查看sys.executable
的文档:
sys.executable
一个字符串,给出Python解释器的可执行二进制文件的绝对路径,在有意义的系统上。如果Python无法检索其可执行文件的实际路径,则sys.executable将为空字符串或None。
python
可能无法检索到这一事实表明它正在使用PATH
sudo设置进行自己的PATH
搜索(根据我对上一个问题的回答)与用于查找可执行文件的内容不同。
这里唯一明确的方法是深入研究python实现,但一般来说我会说版本字符串更可能是你可以信任的。另一方面,sudo
使用execve
来执行命令(至少根据man
页面)。您必须将可执行文件的完整路径指定为execve
(某些exec
变体会执行自己的PATH
搜索,但这一点不会。因此,python
填写sys.executable
我不知道是否有任何方法可以获得argv[0]
解释器的实际python
(sys.argv[0]
始终是脚本的名称或-c
) ,但这会很有趣。如果是/usr/local/bin/python
,这将是python
中的错误。
我认为最好的办法就是在secure_path
中设置/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
程序运行时。
答案 2 :(得分:0)
每次启动python解释器时,shell都会转到/ usr / bin / python并执行它(请尝试下一步:python -c&#34; import os; print(os.environ [&#39; _&#39 ;])&#34)。
那么,你可以看到自己ln -l | grep python
/ usr / bin / python是python解释器可执行文件的软链接。
我做的是:
configure && make && make install
)ln -s <location
最后一个python版本的可执行文件&gt;在/ usr / bin中/蟒蛇
##(很可能需要sudo)sys.version ##它应该是最后一个。