python的Sys.scutable和Sys.version之间的不匹配



安装了两个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.executablesys.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解释器可执行器的软链接。

我所做的是:

  1. 安装python的最后版本(请访问Python的网站,下载最后一个代码和configure && make && make install
  2. 检查该最后版本的可执行文件的位置。
  3. 擦除/usr/bin/python软链接##(您需要root许可sudo)
  4. 上一个Python版本的ln -s <location可执行>/usr/bin/python##(很可能需要Sudo)
  5. 从命令行执行python。
  6. 导入系统

sys.version ##它应该是最后一个。

相关内容

  • 没有找到相关文章

最新更新