os.execl 到底做了什么?为什么我会收到此错误?

发布于 2024-09-29 08:03:22 字数 476 浏览 6 评论 0原文

我在使用 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:在“”中找不到“__main__.py”

那么 os.execl 到底在做什么呢?该错误消息是什么意思?

I'm running into some trouble with deploying Django on the passenger_wsgi module with virtualenv. The Python code in the passenger_wsgi.py file, which should fix my problem is:

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

The first three lines I understand, but I only have a very vague idea about the fourth one and that's the one that happens to be giving me an error:

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

So what is os.execl doing here exactly? And what does that error message mean?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

倦话 2024-10-06 08:03:22

我无意搞乱一个 9 年前的问题,我很快在谷歌上搜索了“Python execl example”并偶然发现了这个帖子,几乎被答案误导了,所以我发帖希望能帮助其他访问者。

我同意 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 脚本,同时成功设置 < 的第一个成员code>sys.argv 到 '',我纯粹猜测代码被复制粘贴到了 REPL。

正如 https://stackoverflow.com/users/845210/bjmc 中提到的.com/questions/4025442/python-os-execl-what-does-it-do-exactly-why-am-i-getting-this-error#comment37742802_4025513">Python: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

可执行文件路径和 main() 中的 argv[0] 之间的不一致使得在类 UNIX 环境,这里有一个脚本来说明这一点:

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。可执行文件)说

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

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

It's not my intention to mess up with a question 9 years old, I googled "Python execl example" shortly and bumped into this thread, almost got misled by the answer, so I'm posting in hope of helping other visitors.

I agree with https://stackoverflow.com/users/479633/mouad about the way to reproduce the bug, but not the reason, the error occurs because when a python interpreter is opened interactively, sys.argv will be [''], so an empty string is passed to the execl-invoked python interpreter as the path to the main script (directory), since the main script file __main__.py cannot be found in directory '' (the current work directory), it complains about:

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

I can not figure out how https://stackoverflow.com/users/211075/monika-sulik managed to run a python script while successfully set the first member of sys.argv to '', it's my pure guess that the code got copy-pasted to the REPL.

As https://stackoverflow.com/users/845210/bjmc mentioned in Python: os.execl() - what does it do exactly? Why am I getting this error?, the documentation is correct, it's OK to pass the interpreter path twice, although not required the second time. The signature of the function has its root in the UNIX execve() API (https://linux.die.net/man/2/execve), which says:

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.

There are programs taking advantage of this inconsistency, e.g. 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

The inconsistency between the executable path and the argv[0] in main() has made getting the reliable path to the running python executable very hard (if not impossible) in a UNIX-like environment, here is a script to illustrate this:

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)

Run this script

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

and sys.executable has value "/bin/ls", as the documentation (https://docs.python.org/3/library/sys.html#sys.executable) says

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

about sys.executable, if the python developers cannot figure out how to get sys.executable point to the path of the running python executable, it probably does not make sense in a UNIX-like environment. I would be grateful if someone tells me otherwise.

淡淡的优雅 2024-10-06 08:03:22

也许你应该这样做:

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

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

关于 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. 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 ''

maybe you should do it like this:

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

i think this doc is wrong : http://wiki.dreamhost.com/Passenger_WSGI

about exec:

The exec functions of Unix-like operating systems are a collection of functions that causes the running process to be completely replaced by the program passed as an argument to the function.

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)

from : http://docs.python.org/library/os.html

The “l” and “v” variants of the exec*() functions differ in how command-line arguments are passed. The “l” variants are perhaps the easiest to work with if the number of parameters is fixed when the code is written; the individual parameters simply become additional parameters to the execl*() functions. The “v” variants are good when the number of parameters is variable, with the arguments being passed in a list or tuple as the args parameter. In either case, the arguments to the child process should start with the name of the command being run, but this is not enforced.

Edit:

i just did what you were doing in a python shell and i get the same error:

>>> 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 ''
猫七 2024-10-06 08:03:22
>>> 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< /a>

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


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

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

This might help with your problem: http://ubuntuforums.org/showthread.php?t=1493979

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文