Andy
Andy

Reputation: 950

subprocess.Popen and shell interpretation

In my current setup, I have

command = "somecommand '%s'" % test
subprocess.Popen(command.split(), stdout=subprocess.PIPE)

The reason why I have inner quotations '' is because I have spaces in test but it should be interpreted as 1 string (a path).

However, what I notice is that the command throws an error because it tries to use the path argument along with its own appended strings so we have ''path'/format' which throws an error.

However when I do somecommand 'path' it will work because the shell I'm guessing will interpret the string? Is this the correct reasoning?

My question is how do I deal with this case where the string needs to be interpreted in the shell before being run through Popen?

Upvotes: 0

Views: 186

Answers (3)

chepner
chepner

Reputation: 531235

The shell isn't processing your command; each part of the list is being passed directly to some member of the exec family of system-level functions.

To have the shell process your command, you need to set the shell argument:

command = "somecommand '%s'" % test
subprocess.Popen(command.split(), shell=True, stdout=subprocess.PIPE)

but a better solution is to skip the shell, in which case you don't need to quote the value:

command = [somecommand, test]
subprocess.Popen(command, stdout=subprocess.PIPE)

Upvotes: 1

Andrew Clark
Andrew Clark

Reputation: 208485

Create your command a list from the beginning:

command = ["somecommand", test]
subprocess.Popen(command, stdout=subprocess.PIPE)

This will work even if test contains spaces because subprocess.Popen() passes each entry in the command list as a single argument.

Upvotes: 3

mgilson
mgilson

Reputation: 309929

You want to use shlex.split to split command:

subprocess.Popen(shlex.split(command),stdout=subprocess.PIPE)

The problem is that str.split doesn't care if you've tried to put something in quotes -- It will split the string on whitespace no matter how much you quote things. e.g.

>>> "foo 'bar baz'".split()
['foo', "'bar", "baz'"]
>>> import shlex
>>> shlex.split("foo 'bar baz'")
['foo', 'bar baz']

Upvotes: 2

Related Questions