Преобразование сложной команды в подпроцесс Python - PullRequest
3 голосов
/ 11 сентября 2011

У меня есть следующая команда:

$ 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 ]

3 голосов
/ 11 сентября 2011

Нет необходимости вызывать perl из Python.

Если у вас есть вывод из ffmpeg в переменной, вы можете сделать что-то вроде этого:

print re.search(r'(\d+x\d+)', str).group()
3 голосов
/ 11 сентября 2011

В общем, вы можете заменить конвейер оболочки этим шаблоном:

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)
0 голосов
/ 11 сентября 2011

Обратите внимание на аргумент «shell» для subprocess.Popen: он указывает, обрабатывается ли передаваемая вами команда оболочкой или нет.

То, что «2>&1» - это одна из тех вещей, которые должны анализироваться оболочкой, в противном случае 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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...