21

I used to be able to do a subprocess.call(["command","-option value -option value"]) and it would work there was a change to the command to work properly with things in quotes, but now I have to change my subprocess call command to look like this:

subprocess.call(["command","-option","value","-option","value"])

is there something I can do to get it to work the other way again in python?

the os.system("command -option value -option value") works the same as it did before.

Blair Conrad
  • 233,004
  • 25
  • 132
  • 111
Dag
  • 1,101
  • 4
  • 11
  • 13

2 Answers2

45

Avoid shell=True if you can -- it's a security risk. For this purpose, shlex.split suffices:

import subprocess
import shlex
subprocess.call(shlex.split("command -option value -option value"))
Community
  • 1
  • 1
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • is this one better than the one above? is there a benefit to using shelex? – Dag Nov 03 '10 at 21:12
  • 3
    `shlex.split` creates a list for you, basically. So it is pretty much equivalent to `subprocess.call(["command","-option","value","-option","value"])` without having to explicitly writing the list literal. – Santa Nov 03 '10 at 21:14
  • 6
    @Dag: it allows you to avoid using `shell=True`, which is a security risk. – unutbu Nov 03 '10 at 23:03
  • why not just use "command -option value -option value".split(" ") – Tom Jun 23 '16 at 00:44
  • 1
    @Tom: `shlex.split` has a better chance of properly splitting a command-line string than `str.split`. For example, `shlex.split("command 'filename with spaces'")` correctly returns `['command', 'filename with spaces']` whereas `"command 'filename with spaces'".split()` incorrectly returns `['command', "'filename", 'with', "spaces'"]`. – unutbu Jun 23 '16 at 01:05
  • @Tom: There are cases where `shlex.split` screws up, however. Such as `shlex.split("""file with \"quotes \'n spaces """)` (which raises a `ValueError`) or `shlex.split(r'C:\Foo')` (the backslash is dropped). So it is sometimes better to manually craft the command/argument list yourself (without `shlex.split` or `str.split`). – unutbu Jun 23 '16 at 01:05
3

You'll need to specify shell=True to get subprocess.call to interpret the string.

See the note in the subprocess.Popen constructor documentation (the subprocess.call method takes the same arguments as the subprocess.Popen constructor).

Blair Conrad
  • 233,004
  • 25
  • 132
  • 111
  • OK, so I did this: subprocess.call("command "+"-option value -option value", shell=True) and it worked. Thanks – Dag Nov 03 '10 at 20:45