18

I am testing out doing some shenanigans with os.execve and virtual environments. I am running into the problem where sys.executable is empty if I replace the current python process with another python subprocess.

The example below shows what's going on (run this inside a python shell):

import os, sys
print(sys.executable) # works this time
os.execve("/usr/bin/python", [], {}) # drops me into a new python shell
import sys # yes, again
print(sys.executable) # is empty

The full output of me running the commands above in a python shell:

 lptp [ tmp ]: python
Python 2.7.10 (default, Oct 14 2015, 16:09:02) 
[GCC 5.2.1 20151010] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os, sys
>>> print(sys.executable) # works this time
/usr/bin/python
>>> os.execve("/usr/bin/python", [], {}) # drops me into a new python shell
Python 2.7.10 (default, Oct 14 2015, 16:09:02) 
[GCC 5.2.1 20151010] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys # yes, again
>>> print(sys.executable) # is empty

>>>

sys.executable being empty is causing me problems, most notably that platform.libc_ver() fails because sys.executable is empty:

>>> import platform
>>> platform.libc_ver()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/platform.py", line 163, in libc_ver
    f = open(executable,'rb')
IOError: [Errno 21] Is a directory: '/tmp'

Note that the example above was run after calling os.execve(...)

d0c_s4vage
  • 3,947
  • 6
  • 23
  • 32
  • What if you pass *os.environ* as the env `os.execve("/usr/bin/python", [], os.environ )`? – Padraic Cunningham Aug 31 '16 at 16:32
  • hrmm, well that works... but only in my simplified example above. In my real code that doesn't make a difference, since I'm already passing in a modified version of my current environment. I'll update my question with a better example. – d0c_s4vage Aug 31 '16 at 16:34
  • Well if sys.executable is None or an empty string then it cannot be found so it is definitely related to passing an empty dict as env. – Padraic Cunningham Aug 31 '16 at 16:36
  • I get an equivalent issue from running python using `env -i` such as `env -i python /usr/local/lib/python2.7/dist-packages/virtualenv.py ~/jenkins/workspace/analysis_super__Python_tests/venv`, in which case virtualenv.py does not have a valid sys.executable. – sage Feb 26 '18 at 01:55
  • Probing deeper, I see that this is easier to get around with `env -i` than it is with the OP's execve issue. Whereas `env -i python -c 'import sys ; print(sys.executable)'` gives an empty result, just giving the full path with `env -i /usr/bin/python -c 'import sys ; print(sys.executable)'` gives the expected result. – sage Feb 26 '18 at 02:02

1 Answers1

12

Python relies on argv[0] and several environment variables to determine sys.executable. When you pass an empty argv and environment, Python doesn't know how to determine its path. At the very least, you should provide argv[0]:

os.execve('/usr/bin/python', ['/usr/bin/python'], {})
user2357112
  • 260,549
  • 28
  • 431
  • 505