Python:os.execl()- 它究竟做什么?为什么我会得到这个错误?

2024-05-14 23:15:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我在使用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.exec到底在这里做什么呢?那个错误信息是什么意思?


Tags: 模块namepyenvwsgihomebinvirtualenv
3条回答

我无意搞乱一个9岁大的问题,我很快就在谷歌上搜索了“Python execl example”,碰到这个帖子,差点被答案误导,所以我发帖希望能帮助其他访问者。

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

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

我不知道https://stackoverflow.com/users/211075/monika-sulik如何在成功地将sys.argv的第一个成员设置为''的同时运行python脚本,我只是猜测代码被复制粘贴到REPL。

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

argv is an array of argument strings passed to the new program. By convention, the first of these strings should contain the filename associated with the file being executed.

有些程序利用了这种不一致性,例如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

可执行路径和main()中的argv[0]之间的不一致使得在类UNIX环境中获取运行的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)所说

A string giving the absolute path of the executable binary for the Python interpreter, on systems where this makes sense.

关于sys.executable,如果python开发人员不知道如何让sys.executable指向正在运行的python可执行文件的路径,那么在类似UNIX的环境中可能没有意义。如果有人不告诉我,我会很感激的。

>>> 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

也许你应该这样做:

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 ''

相关问题 更多 >

    热门问题