Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing double quote shell commands in python to subprocess.Popen()?

I've been trying to pass a command that works only with literal double quotes in the commandline around the "concat:file1|file2" argument for ffmpeg.

I cant however make this work from python with subprocess.Popen(). Anyone have an idea how one passes quotes into subprocess.Popen?

Here is the code:

command = "ffmpeg -i "concat:1.ts|2.ts" -vcodec copy -acodec copy temp.mp4"  output,error = subprocess.Popen(command, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() 

When I do this, ffmpeg won't take it any other way other than quotes around the concat segement. Is there a way to successfully pass this line to subprocess.Popen command?

like image 270
Fight Fire With Fire Avatar asked Feb 18 '13 03:02

Fight Fire With Fire


People also ask

How do you pass a string with double quotes in Python?

By using the escape character \" we are able to use double quotes to enclose a string that includes text quoted between double quotes. Similarly, we can use the escape character \' to add an apostrophe in a string that is enclosed in single quotes: print('Sammy\'s balloon is red. ')

What is shell true in subprocess Popen?

Setting the shell argument to a true value causes subprocess to spawn an intermediate shell process, and tell it to run the command. In other words, using an intermediate shell means that variables, glob patterns, and other special shell features in the command string are processed before the command is run.

How subprocess popen works in Python?

The subprocess module defines one class, Popen and a few wrapper functions that use that class. The constructor for Popen takes arguments to set up the new process so the parent can communicate with it via pipes. It provides all of the functionality of the other modules and functions it replaces, and more.


2 Answers

I'd suggest using the list form of invocation rather than the quoted string version:

command = ["ffmpeg", "-i", "concat:1.ts|2.ts", "-vcodec", "copy",            "-acodec", "copy", "temp.mp4"] output,error  = subprocess.Popen(                     command, universal_newlines=True,                     stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() 

This more accurately represents the exact set of parameters that are going to be passed to the end process and eliminates the need to mess around with shell quoting.

That said, if you absolutely want to use the plain string version, just use different quotes (and shell=True):

command = 'ffmpeg -i "concat:1.ts|2.ts" -vcodec copy -acodec copy temp.mp4' output,error  = subprocess.Popen(                     command, universal_newlines=True, shell=True,                     stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() 
like image 111
Amber Avatar answered Sep 19 '22 10:09

Amber


Either use single quotes 'around the "whole pattern"' to automatically escape the doubles or explicitly "escape the \"double quotes\"". Your problem has nothing to do with Popen as such.

Just for the record, I had a problem particularly with a list-based command passed to Popen that would not preserve proper double quotes around a glob pattern (i.e. what was suggested in the accepted answer) under Windows. Joining the list into a string with ' '.join(cmd) before passing it to Popen solved the problem.

like image 43
j08lue Avatar answered Sep 18 '22 10:09

j08lue