20

For example I am using ffplay and want to run this command -bufsize[:stream_specifier] integer (output,audio,video)

At the moment I have this:

subprocess.call(["ffplay", "-vn", "-nodisp","-bufsize 4096", "%s" % url])

But this says it is invalid.

rypel
  • 4,686
  • 2
  • 25
  • 36
user673906
  • 757
  • 6
  • 15
  • 30

3 Answers3

26

As JBernardo mentioned in a comment, separate the "-bufsize 4096" argument into two, "-bufsize", "4096". Each argument needs to be separated when subprocess.call is used with shell=False (the default). You can also specify shell=True and give the whole command as a single string, but this is not recommended due to potential security vulnerabilities.

You should not need to use string formatting where you have "%s" % url. If url is a string, pass it directly, otherwise call str(url) to get a string representation.

Abe Karplus
  • 8,350
  • 2
  • 27
  • 24
6

This is the way to go:

url = 'http://www.whatever.com'
cmd = 'ffplay -vn -nodisp -bufsize 4096 '.split()
subprocess.call(cmd + [str(url)], shell=False)
Adi
  • 5,089
  • 6
  • 33
  • 47
Fabrizio
  • 437
  • 3
  • 14
  • 2
    What if `url` contains spaces? – Abe Karplus Jul 27 '12 at 18:54
  • 5
    That was my point, that this is not "the way to go" because it is rather fragile. – Abe Karplus Jul 30 '12 at 15:09
  • I think it would be fragile if one url out of 5 was containing spaces. Don't you think? – Fabrizio Jul 31 '12 at 08:00
  • It's fragile because it breaks on some valid input. If only one URL in 100 contains spaces, it makes the problem that much harder to debug when it occurs. There's an easy way to avoid this bug, too; see my solution. – Abe Karplus Jul 31 '12 at 15:31
  • You are right. Can you please modify my code so that it includes your solution. – Fabrizio Aug 02 '12 at 09:37
  • I've edited your answer with my solution, though it is still in the peer-review queue currently. – Abe Karplus Aug 02 '12 at 15:55
  • 1
    "bukzor", why don't you tell us why? – Fabrizio Aug 03 '12 at 09:56
  • 1
    This works for this particular set of arguments, but if any of the arguments *other* than the url contains a space (and is quoted), then it will still break. Using `shlex.split` deals with these kinds of corner cases. – lvc May 22 '13 at 12:23
  • I really like the use of .split() in this example. It makes it super easy to take a normal command-line, paste it into a variable and split it for consumption by subprocess. – jatal Jun 19 '13 at 21:57
3

While using shlex.split() is overkill for your use case, many of the comments seem to be asking about the use of spaces in parameters in cases where a CLI allows you to pass in quoted strings containing spaces (i.e. git commit -m "Commit message here").

Here is a quick python function that can be used to run commands including parameters with spaces:

import shlex, subprocess

def run_command( command ):
    subprocess.call(shlex.split(command))
MoralCode
  • 1,954
  • 1
  • 20
  • 42