7

我在使用 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 到底在做什么呢?那条错误消息是什么意思?

4

3 回答 3

6

也许你应该这样做:

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

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

关于执行:

类 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 ''
于 2010-10-26T16:01:04.133 回答
6

我无意搞砸一个 9 岁的问题,我很快在谷歌上搜索了“Python execl 示例”并碰到了这个线程,几乎被答案误导了,所以我发帖希望能帮助其他访问者。

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

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

我无法弄清楚https://stackoverflow.com/users/211075/monika-sulik如何在成功设置第一个成员的同时成功运行 python 脚本sys.argvto '',我纯粹猜测代码已复制粘贴到 REPL .

正如Python中提到的https://stackoverflow.com/users/845210/bjmc:os.execl () - 它究竟做了什么?为什么我会收到此错误?,文档是正确的,通过两次解释器路径是可以的,虽然第二次不需要。该函数的签名根植于 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

argv[0]可执行文件路径和in之间的不一致main()使得在类 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)所说

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

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

于 2018-11-05T08:32:30.940 回答
-2
>>> 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

于 2010-10-26T15:55:59.763 回答