3

I found most of the programmers suggest use list of strings to represent the command in popen. However, in my own project, I found a whole string works in more cases.

For example, the following works

subprocess.Popen('pgrep -f "\./run"', stdout=subprocess.PIPE, shell=True).wait()

while

subprocess.Popen(['pgrep', '-f', '"\./run"'], stdout=subprocess.PIPE, shell=True).wait()

does not.

May I know what's the difference between these two ways of implementation and why the second one does not work as expected?

Jerry Chou
  • 302
  • 1
  • 11
  • 2
    See [this post](http://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess). In this case your better version fails because your argument should be `'\./run'` and not `'"\./run"'`. I'd go so far as to say that you should never, ever use `shell=True`. – that other guy Jan 27 '16 at 03:37
  • But if the command depends on some environment settings, I will need to use `shell=True`, right? @thatotherguy – Jerry Chou Jan 27 '16 at 06:53
  • Any command would inherit the same environment variables as a shell would, unless the environment is set up in the shell's init files. If you have a specific, good reason to require a shell, it would be better to explicitly invoke it like `['/bin/bash', '-c', 'some shell command', 'args...']` as this lets you choose the shell to depend on and more safely pass in data. – that other guy Jan 27 '16 at 20:19
  • Got it, thanks a lot! @thatotherguy – Jerry Chou Feb 01 '16 at 06:43

1 Answers1

4

The second should not have a shell=True parameter. Instead, it should be: subprocess.Popen(['pgrep', '-f', '"\./run"'], stdout=subprocess.PIPE).wait().

The shell parameter sets whether or not to execute the command in a separate shell. That is, if a new shell should be spawned just to execute the command, which must be interpreted by the shell before it can be run.

When providing a list of strings, however, this does not spawn a second shell, and thus is (minimally) faster. It is also better to use for processing variable input, because it avoids string interpolation.

See: https://stackoverflow.com/a/15109975/1730261

Community
  • 1
  • 1
Rushy Panchal
  • 16,979
  • 16
  • 61
  • 94
  • 1
    Passing a list with `shell=True` will not immediately fail on Windows, but is arguably wrong nevertheless. On Unix-like platforms, it will "mysteriously" lose the items after the first. Maybe see also https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess – tripleee Jan 29 '20 at 10:37