将复杂命令转换为python子进程

时间:2011-09-10 21:10:55

标签: python subprocess

我有以下命令:

$ ffmpeg -i http://url/1video.mp4 2>&1 | perl -lane 'print $1 if /(\d+x\d+)/'
640x360

我正在尝试将此命令的输出设置为python变量。以下是我到目前为止的情况:

>>> from subprocess import Popen, PIPE
>>> p1 = Popen(['ffmpeg', '-i', 'http://url/1video.mp4', '2>&1'], stdout=PIPE)
>>> p2=Popen(['perl','-lane','print $1 if /(\d+x\d+)/'], stdin=p1.stdout, stdout=PIPE)
>>> dimensions = p2.communicate()[0]
''

我在这里做错了什么,以及如何获得尺寸的正确值?

3 个答案:

答案 0 :(得分:3)

一般情况下,您可以replace a shell pipeline使用此模式:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]

但是,在这种情况下,不需要管道:

import subprocess
import shlex
import re
url='http://url/1video.mp4'
proc=subprocess.Popen(shlex.split('ffmpeg -i {f}'.format(f=url)),
                      stdout=subprocess.PIPE,
                      stderr=subprocess.PIPE)
dimensions=None
for line in proc.stderr:
    match=re.search(r'(\d+x\d+)',line)
    if match:
        dimensions=match.group(1)
        break
print(dimensions)

答案 1 :(得分:3)

无需在python中调用perl

如果你在变量中有ffmpeg的输出,你可以这样做:

print re.search(r'(\d+x\d+)', str).group()

答案 2 :(得分:0)

注意shell的“subprocess.Popen”参数:这指定您传递的命令是否由shell解析。

2>&1”是需要由shell解析的事情之一,否则FFmpeg(与大多数程序一样)会尝试将其视为文件名或选项值。

最接近原始模仿的Python序列可能更像是

p1 = subprocess.Popen("ffmpeg -i http://url/1video.mp4 2>&1", shell = True, stdout = subprocess.PIPE)<BR>
p2 = subprocess.Popen(r"perl -lane 'print $1 if /(\d+x\d+)/'", shell = True, stdin = p1.stdout, stdout = subprocess.PIPE)<BR>
dimensions = p2.communicate()[0]