Python:os.execl() - 它究竟做了什么?为什么我收到此错误?

时间:2010-10-26 15:52:28

标签: python virtualenv os.execl

我在使用virtualenv在passenger_wsgi模块上部署Django时遇到了一些麻烦。 passenger_wsgi.py文件中的Python代码应该解决我的问题:

import os, sys
INTERP = '/home/login/.virtualenvs/env_name/bin/python'
if sys.executable != INTERP:
    os.execl(INTERP, INTERP, *sys.argv)

我理解的前三行,但我对第四行只有一个含糊不清的想法,那就是碰巧给我一个错误:

  

/home/login/.virtualenvs/env_name/bin/python: can't find '__main__.py' in ''

那么os.execl到底在做什么呢?那个错误信息意味着什么?

3 个答案:

答案 0 :(得分:5)

也许你应该这样做:

os.execl(INTERP, *sys.argv) # don't pass again the interpreter path. 

我认为这个文档错了:http://wiki.dreamhost.com/Passenger_WSGI

关于exec:

类Unix操作系统的exec函数是一组函数,它们使运行过程完全被作为函数参数传递的程序所取代。

os.execl(path, arg0, arg1, ...)
os.execle(path, arg0, arg1, ..., env)
os.execlp(file, arg0, arg1, ...)
os.execlpe(file, arg0, arg1, ..., env)
os.execv(path, args)
os.execve(path, args, env)
os.execvp(file, args)
os.execvpe(file, args, env)

来自: http://docs.python.org/library/os.html

exec *()函数的“l”和“v”变体在命令行参数的传递方式上有所不同。如果在编写代码时参数的数量是固定的,那么“l”变体可能是最容易使用的;各个参数只是成为execl *()函数的附加参数。当参数的数量是可变的时,“v”变体是好的,参数在列表或元组中作为args参数传递。在任何一种情况下,子进程的参数都应该从正在运行的命令的名称开始,但不会强制执行。

修改

我刚刚在python shell中做了你正在做的事情,我得到了同样的错误:

>>> import os
>>> import sys
>>> os.execl('/home/login/projects/virtual/bin/python', '/home/login/projects/virtual/bin/python', *sys.argv)
/home/login/projects/virtual/bin/python: can't find '__main__.py' in ''

答案 1 :(得分:1)

我不是要搞一个9岁的问题,我不久后在Google上搜索了“ Python execl示例”并碰到了这个线程,几乎被答案所迷惑,所以我发帖希望对其他访问者有所帮助。

我同意https://stackoverflow.com/users/479633/mouad的错误重现方式,但并非如此,原因是发生错误是因为以交互方式打开python解释器时,sys.argv将是[''],因此一个空字符串作为主脚本(目录)的路径传递给调用execl的python解释器,因为在目录``(当前工作目录)中找不到主脚本文件__main__.py,它抱怨:< / p>

can't find '__main__.py' in ''

我无法弄清楚https://stackoverflow.com/users/211075/monika-sulik如何成功地将sys.argv的第一个成员设置为''时运行了python脚本,这纯粹是我的代码被复制粘贴了。到REPL。

正如https://stackoverflow.com/users/845210/bjmc中提到的Python: os.execl() - what does it do exactly? Why am I getting this error?一样,文档是正确的,可以两次通过解释器路径,尽管第二次不需要。该函数的签名的根源是UNIX execve() API(https://linux.die.net/man/2/execve),它表示:

  

argv是传递给新程序的参数字符串数组。通过   约定,这些字符串中的第一个应包含文件名   与正在执行的文件关联。

有些程序利用了这种不一致,例如busybox。

$ ln -s /bin/busybox cat
$ ./cat /etc/timezone
/UTC
$ python -c "import os; os.execl('./cat', 'cat', '/etc/timezone')"
/UTC
$ python -c "import os; os.execl('./cat', 'ls', '/etc/timezone')"
/etc/timezone

在类似UNIX的环境中,可执行文件路径与argv[0]中的main()之间的不一致使得很难获得(即使不是不可能)通往正在运行的python可执行文件的可靠路径,这是一个脚本来说明这一点:

import os
import sys


if len(sys.argv) >= 2 and sys.argv[1] == 'exec':
    os.execl('/usr/bin/python', 'ls', sys.argv[0])
else:
    print(sys.executable)
    print(sys.version)
    print(sys.argv)

运行此脚本

$ python test.py exec
/bin/ls
2.7.13 (default, Nov 24 2017, 17:33:09)
[GCC 6.3.0 20170516]
['test.py']

并且sys.executable的值为"/bin/ls",如文档(https://docs.python.org/3/library/sys.html#sys.executable)所述

  

一个字符串,给出了可执行二进制文件的绝对路径   Python解释器,在有意义的系统上

关于sys.executable,如果python开发人员无法弄清楚如何使sys.executable指向正在运行的python可执行文件的路径,则在类似UNIX的环境中可能没有意义。如果有人另外告诉我,我将不胜感激。

答案 2 :(得分:-1)

>>> import os
>>> help(os.execl)


execl(file, *args)
    execl(file, *args)

    Execute the executable file with argument list args, replacing the
    current process.

这可能会对您的问题有所帮助:http://ubuntuforums.org/showthread.php?t=1493979