2010-03-22 19 views
13

Sto provando a usare subprocess.Popen per costruire una sequenza per afferrare la durata di un file video. Ho cercato per 3 giorni, e non riesco a trovare alcun motivo in linea sul motivo per cui questo codice non funziona, ma continua a darmi un risultato vuoto:Utilizzare correttamente subprocess.PIPE in 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

perché stai usando grep, sed tagliare e per analizzare l'output invece di utilizzare le funzioni di Python built? –

+1

[subprocess.PIPE] (http://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/) è il tuo nemico – ldgorman

risposta

14

stderr deve essere reindirizzato allo stdout. Inoltre, non c'è bisogno di chiamare altri strumenti come cut/sed ecc fare la manipolazione di stringhe in 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] 

Se Python non è un must, è possibile utilizzare direttamente il guscio.

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

Grazie. Non mi rendevo conto che dovevo reindirizzare 'stderr' pure. –

13

Utilizzando subprocess.PIPE non sarà magicamente cablare il tubi corretti per te.

È necessario passare il tubo di uscita del primo processo come valore per il parametro stdin del secondo processo. See the docs for an example.

4

Python non può "costruire un'intera pipeline" in questo modo - potrebbe delegare l'attività alla shell, o incollarla più direttamente usando gli attributi stdout dei precedenti oggetti di sottoprocesso nella linea, ma non c'è davvero motivo per questo in questo caso specifico, dal momento che è possibile codificarlo direttamente in Python abbastanza facilmente. Es .:

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

Come altri hanno sottolineato, è necessario passare il PIPE da un processo a quello successivo. Lo stdout (PIPE) da un processo diventa lo stdin per la seguente attività.

Qualcosa di simile a questo (a partire dal vostro esempio):

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

Considererei questa la risposta corretta, risponde esattamente a ciò che ha chiesto OP e non sta istruendo su come si potrebbe aggirare. – Beli

Problemi correlati