Правильно использовать subprocess.PIPE в python?
Я пытаюсь использовать subprocess.Popen
для построения последовательности, чтобы захватить продолжительность видеофайла. Я искал 3 дня и не могу найти причину онлайн, почему этот код не работает, но он продолжает давать мне пустой результат:
import sys
import os
import subprocess
def main():
the_file = "/Volumes/Footage/Acura/MDX/2001/Crash Test/01 Acura MDX Front Crash.mov"
ffmpeg = subprocess.Popen(['/opt/local/bin/ffmpeg', '-i', the_file], stdout = subprocess.PIPE, )
grep = subprocess.Popen(['grep', 'Duration'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, )
cut = subprocess.Popen(['cut', '-d', ' ', '-f', '4'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, )
sed = subprocess.Popen(['sed', 's/,//'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, )
duration = sed.communicate()
print duration
if __name__ == '__main__':
main()
Ответы
Ответ 1
stderr необходимо перенаправить на stdout. Кроме того, нет необходимости вызывать другие инструменты, такие как cut/sed
и т.д., Ваши строковые манипуляции в Python
import subprocess
....
the_file = "/Volumes/Footage/Acura/MDX/2001/Crash Test/01 Acura MDX Front Crash.mov"
ffmpeg = subprocess.Popen(['/usr/bin/ffmpeg', '-i', the_file], stderr=subprocess.STDOUT,stdout = subprocess.PIPE )
out, err = ffmpeg.communicate()
if "Duration" in out:
print out[out.index("Duration"):].split()[1]
Если Python не является обязательным, вы можете напрямую использовать оболочку.
the_file="/Volumes/Footage/Acura/MDX/2001/Crash Test/01 Acura MDX Front Crash.mov"
ffmpeg -i "$file" 2>&1 | awk '/Duration/{print $2}'
Ответ 2
Как указывали другие, вам необходимо передать PIPE из одного процесса в другой.
Stdout (PIPE) из одного процесса становится stdin для следующей задачи.
Что-то вроде этого (начиная с вашего примера):
import sys
import os
import subprocess
def main():
the_file = "/Volumes/Footage/Acura/MDX/
2001/Crash Test/01 Acura MDX Front Crash.mov"
ffmpeg = subprocess.Popen(['/opt/local/bin/ffmpeg', '-i', the_file],
stdout = subprocess.PIPE)
grep = subprocess.Popen(['grep', 'Duration'],
stdin = ffmpeg.stdout, stdout = subprocess.PIPE)
cut = subprocess.Popen(['cut', '-d', ' ', '-f', '4'],
stdin = grep.stdout, stdout = subprocess.PIPE)
sed = subprocess.Popen(['sed', 's/,//'],
stdin = cut.stdout, stdout = subprocess.PIPE)
duration = sed.communicate()[0]
print duration
if __name__ == '__main__':
main()
Ответ 3
Использование subprocess.PIPE
не приведет к магическому подключению правильных труб для вас.
Вы должны передать выходной канал первого процесса в качестве значения параметра stdin
второго процесса. См. документы для примера.
Ответ 4
Python не может "построить целый конвейер" таким образом - он может делегировать задачу оболочке или склеить ее более непосредственно, используя атрибуты stdout
предыдущих объектов подпроцесса в строке, но там действительно нет причин для этого в этом конкретном случае, так как вы можете легко его закодировать прямо в Python. Например:.
ffmpeg = subprocess.Popen(['/opt/local/bin/ffmpeg', '-i', the_file],
stdout=subprocess.PIPE)
for line in ffmpeg.stdout:
if 'Duration' not in line: continue
fields = line.split()
duration = fields[4].replace(',', '')
break