Правильно ли использовать subprocess.PIPE в python? - PullRequest
13 голосов
/ 22 марта 2010

Я пытаюсь использовать 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()

Ответы [ 4 ]

24 голосов
/ 06 августа 2013

Как уже отмечали другие, вам нужно передать ТРУБУ от одного процесса к другому. Стандартный вывод (PIPE) из одного процесса становится стандартным для следующей задачи.

Примерно так (начиная с вашего примера):

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()
15 голосов
/ 22 марта 2010

stderr необходимо перенаправить на стандартный вывод. Кроме того, нет необходимости вызывать другие инструменты, такие как 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}'
13 голосов
/ 22 марта 2010

Использование subprocess.PIPE не сможет магически соединить правильные трубы для вас.

Вы должны передать выходной канал первого процесса в качестве значения параметра stdin второго процесса. См. Документацию для примера .

4 голосов
/ 22 марта 2010

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...