Reputation: 1095
I'm trying to run a command using the python subprocess
package. I've added the path to the compiled executable to my PATH
on an Ubuntu machine.
When I do this, it works:
myexecutable input_file output_file
When I do this, it works:
import subprocess
import shlex
cmd = '/path/to/my/myexecutable input_file output_file'
subprocess.Popen(shlex.split(cmd))
Here's the kicker. When I do this, it doesn't work:
import subprocess
import shlex
cmd = 'myexecutable input_file output_file'
subprocess.Popen(shlex.split(cmd))
It gives me:
OSError Traceback (most recent call last)
<ipython-input-4-8f5c3da8b0a3> in <module>()
----> 1 subprocess.call(shlex.split(cmd))
/home/me/miniconda3/envs/mypy2/lib/python2.7/subprocess.pyc in call(*popenargs, **kwargs)
170 retcode = call(["ls", "-l"])
171 """
--> 172 return Popen(*popenargs, **kwargs).wait()
173
174
/home/me/miniconda3/envs/mypy2/lib/python2.7/subprocess.pyc in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags)
392 p2cread, p2cwrite,
393 c2pread, c2pwrite,
--> 394 errread, errwrite)
395 except Exception:
396 # Preserve original exception in case os.close raises.
/home/me/miniconda3/envs/mypy2/lib/python2.7/subprocess.pyc in _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, to_close, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite)
1045 raise
1046 child_exception = pickle.loads(data)
-> 1047 raise child_exception
1048
1049
OSError: [Errno 2] No such file or directory
What gives?
Upvotes: 2
Views: 1896
Reputation: 168824
Whatever shell you're using (as well as subprocess.Popen(..., shell=True)
, but that comes with caveats) figures out the actual executable based on the PATH
environment variable.
subprocess.Popen()
by itself does not. One popular way to work around this (i.e. to do that path lookup) on UNIX systems is using the widely available /usr/bin/env
tool which does the same expansion, i.e.
subprocess.Popen(['/usr/bin/env', 'mytool', 'hurr', 'durr'])
but that's not portable for Windows.
The best way to go about things is to do the lookup by yourself, that is to figure out the full path of your executable file and pass it to subprocess.Popen()
– os.path.realpath()
might be your friend here.
Upvotes: 1