安装了两个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如何修改路径,我可以理解sys.executable
的值。但是,为什么sys.version
报告版本2.7.6而不是版本2.4.3,哪些将与sys.executable
报告的usr/bin/python
路径匹配?
这是我问题sudo更改路径的后续措辞,但执行相同的二进制
两者都@graeme
Python可能无法检索的事实表明 正在做自己的路径搜索(…)
和@twalberg
(…)看起来像sys.cutable搜索当前路径而不是 解决argv [0](或者因为argv [0]是simpy python 案例...),(…)
基本上是正确的。我不愿意相信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()
在同一文件中定义,并包含以下注释:
/* 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
文件的顶部找到有关计算解释器可执行文件位置的过程的更多信息:
在完成任何搜索之前,可执行文件的位置为 决定。如果argv [0]中有一个或多个斜线,则使用它 不变。否则,它一定是从外壳的路径中调用的, 因此,我们搜索$路径以获取命名的可执行文件并使用它。如果是 在$路径上找不到可执行文件(或没有$路径环境 变量),使用原始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)]
好的。
如果在$路径上找不到可执行文件(或没有$路径环境变量),则使用原始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)]
错误。在这种情况下,来自SYS模块文档的语句是正确的 - 如果Python无法检索其可执行文件的真实路径,则SYS.Executable将是一个空字符串。。。
让我们看看是否将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)]
它做到了。
相关:
- Python问题7774 - Sys.scutable:错误的位置,如果修改了Zeroth命令参数。
- Python问题10835 - SYS.Ectable默认值和Altinstall
- python-dev邮件列表线程 - 朝着更严格的sys.cutable定义
- stackoverflow问题 - 如何在C 中找到可执行文件的位置
我认为/usr/local/bin/python
是正在运行的可执行文件。版本字符串几乎可以肯定地编译到python
中,因此不可能是错误的。查看sys.executable
的文档:
sys.ecutable
一个字符串为Python解释器提供了可执行二进制的绝对路径,这是有道理的。如果Python无法检索其可执行文件的真实路径,则Sys.cutable将是一个空字符串或无。
python
可能无法检索的事实表明,它正在使用PATH
Sudo设置自己的PATH
搜索(根据我对上一个问题的回答,这与它用于查找该问题的问题不同可执行)。
在这里确定的唯一方法是挖掘Python实现,但通常我会说,版本字符串更有可能是您可以信任的一个。另一方面,sudo
使用execve
执行命令(至少根据man
页面)。您必须为execve
的可执行文件指定(exec
变体中的某些PATH
搜索,这是没有)。因此,python
填充sys.executable
应该是不介意的。
我不知道是否有任何方法可以获取python
解释器的实际argv[0]
(sys.argv[0]
始终是脚本或-c
的名称),但这很有趣。如果是/usr/local/bin/python
,这将是python
中的错误。
我认为最好的办法就是在/etc/sudoers
中设置secure_path
,希望您会获得一些一致性。
更新
实际上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
当程序运行时。
每次启动python解释器时,shell将转到/usr/bin/python并执行它(尝试一下)下一篇:Python -c"导入OS; print(os.environ ['_'])")。
好吧,您可以看到自己ln -l | grep python
/usr/bin/python是python解释器可执行器的软链接。
我所做的是:
- 安装python的最后版本(请访问Python的网站,下载最后一个代码和
configure && make && make install
) - 检查该最后版本的可执行文件的位置。
- 擦除/usr/bin/python软链接##(您需要root许可sudo)
- 上一个Python版本的
ln -s <location
可执行>/usr/bin/python##(很可能需要Sudo) - 从命令行执行python。
- 导入系统
sys.version ##它应该是最后一个。