如何在Python中将双引号Shell命令传递给subprocess.Popen()?

70 投票
7 回答
79091 浏览
提问于 2025-04-17 16:13

我一直在尝试在命令行中传递一个只接受字面双引号的命令,这个命令是关于"concat:file1|file2"的,主要用于ffmpeg。

不过,我在用subprocess.Popen()从Python中实现这个功能时遇到了问题。有没有人知道怎么把引号传递给subprocess.Popen?

这是我的代码:

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()

当我这样做时,ffmpeg只接受在concat部分周围加引号的方式。有没有办法成功将这一行传递给subprocess.Popen命令?

7 个回答

9

这个内容适用于 Python 2.7.3。把错误信息输出到标准输出的命令在旧版本的 Python 中有所不同:

把下面的代码放到一个叫做 test.py 的文件里:

#!/usr/bin/python
import subprocess

command = 'php -r "echo gethostname();"'
p = subprocess.Popen(command, universal_newlines=True, shell=True, 
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
text = p.stdout.read()
retcode = p.wait()
print text

然后运行这个文件:

python test.py

它会打印出我的主机名,主机名是 apollo:

apollo

想了解更多,可以查看 subprocess 的手册: http://docs.python.org/2/library/subprocess.html

12

你可以用单引号 '把整个模式包起来',这样就能自动处理双引号,或者你也可以直接 "用反斜杠来转义\"双引号\""。你的问题其实和 Popen 没有关系。

顺便说一下,我之前遇到过一个问题,就是在 Windows 系统下,传给 Popen 的一个基于 list 的命令,没有正确保留双引号在通配符模式周围(也就是在被接受的答案中提到的那种情况)。在把这个列表用 ' '.join(cmd) 连接成一个字符串后再传给 Popen,问题就解决了。

72

我建议你使用列表的方式来调用,而不是用字符串的方式:

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()

这样做更准确地表示了将要传递给最终处理的参数集合,而且不需要去处理那些复杂的引号问题。

不过,如果你真的想用普通字符串的方式,只需使用不同的引号(并且加上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()

撰写回答