2010-03-22 7 views
13

Próbuję użyć subprocess.Popen do skonstruowania sekwencji, aby pobrać czas pliku wideo. Szukałem na 3 dni i nie mogę znaleźć żadnego powodu, on-line, dlaczego ten kod nie działa, ale to wciąż daje mi pusty wynik: Używanie subprocess.PIPE nie będzie magicznie OkablowaćWłaściwie używając podprocesu.PIPE w pythonie?

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

Dlaczego używasz grep, sed cięte i do analizowania danych wyjściowych zamiast używać wbudowanych funkcji Python? –

+1

[subprocess.PIPE] (http://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/) jest Twoim wrogiem. – ldgorman

Odpowiedz

14

stderr należy przekierować na stdout. Ponadto, nie ma potrzeby, aby zadzwonić do innych narzędzi, jak cut/sed itp wykonać manipulacji ciąg w Pythonie

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] 

Jeśli Python nie jest koniecznością, można użyć bezpośrednio powłokę.

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

Dziękuję. Nie zdawałem sobie sprawy, że muszę również przekierować 'stderr'. –

13

popraw rury dla ciebie.

Musisz przełączyć rurę wyjściową pierwszego procesu jako wartość dla parametru stdin drugiego procesu. See the docs for an example.

4

Python nie może "zbudować całego rurociągu" w ten sposób - mógłby przekazać zadanie do powłoki lub przykleić je bardziej bezpośrednio, używając atrybutów stdout poprzednich obiektów podprocesu w linii, ale tak naprawdę nie ma z tego powodu w tym konkretnym przypadku, ponieważ można go łatwo kodować bezpośrednio w Pythonie. Np .:

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

Jak podkreślali inni, musisz przejść PIPE z jednego procesu do następnego. Stdout (PIPE) z jednego procesu staje się stdin dla następującego zadania.

Coś jak to (zaczynając od przykładu):

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

Uznalbym to za poprawną odpowiedź, odpowiada dokładnie na to, co OP zadał i nie pouczał, jak można obejść to. – Beli

Powiązane problemy