2

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?

8
  • 3
    What exactly is the difference between the 2 ways of using subprocess? Am I blind? They look the same to me... Commented Mar 8, 2019 at 19:55
  • 3
    Your works/doesn't work appear identical. Commented Mar 8, 2019 at 19:55
  • They are identical. He's trying to trick us the b*****d lol Commented Mar 8, 2019 at 20:09
  • whoops. lemme fix that Commented Mar 8, 2019 at 20:10
  • 2
    The two ways are not identical folks. One has an absolute path the other doesn't — and I suspect that's why one works and the other doesn't (because one is relative to the current working directory). Commented Mar 8, 2019 at 21:24

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Your answer is confusing. I think all you need to say is that "myexecutable" is not in path. Using env is not going to help him in any way.
But popen itself will not do path expansion.
Oh. Like I said, your wording is confusing :)
@MK. Better now?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.