2010-03-22 3 views
13

Я пытаюсь использовать subprocess.Popen для создания последовательности, чтобы захватить продолжительность видеофайла. Я искал в течение 3 дней, и не может найти причину онлайн, почему этот код не работает, но он продолжает давать мне пустой результат:Правильно использовать subprocess.PIPE в python?

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

Почему вы используете Grep, вырезать и СЭД для разбора вывода вместо того, чтобы использовать встроенные функции Python? –

+1

[subprocess.PIPE] (http://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/) - ваш враг – ldgorman

ответ

14

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}' 
+0

Спасибо. Я не понимал, что мне пришлось перенаправить «stderr». –

13

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

Вы должны передать выходной канал первого процесса в качестве значения для параметра stdin второго процесса. See the docs for an example.

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 
23

Как указывалось другими, вам необходимо передать 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

Я бы счел правильным ответ, он точно отвечает за то, что спросил ОП, и не дает инструкции о том, как вы могли бы обойти его. – Beli

Смежные вопросы