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.