2010-03-22 4 views
13

subprocess.Popen을 사용하여 비디오 파일의 길이를 얻기 위해 시퀀스를 구성하려고합니다. 나는 3 일을 찾고 있었고,이 코드가 작동하지 않는 이유에 온라인 어떤 이유를 찾을 수 있지만, 그것은 나에게 빈 결과 제공 유지 : 마술를 연결하지 않습니다 subprocess.PIPE를 사용python에서 subprocess.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 = 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을 사용하는 대신 내장 파이썬 함수를 사용하는 출력을 구문 분석 나오지입니까? –

+1

[subprocess.PIPE] (http://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/)는 적입니다. – ldgorman

답변

14

stderr을 stdout으로 리디렉션해야합니다. 또한, 파이썬은 필수가 아닌 경우

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] 

파이썬

에 문자열 조작을 cut/sed 등과 같은 다른 도구를 호출 할 필요가 없습니다, 당신은 직접 쉘을 사용할 수 있습니다.

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

을 올바른 파이프를 찾으십시오.

첫 번째 프로세스의 출력 파이프를 두 번째 프로세스의 매개 변수 stdin 값으로 전달해야합니다. See the docs for an example.

4

파이썬은 이런 방식으로 "전체 파이프 라인"을 구축 할 수 없습니다. 즉, 쉘에 작업을 위임하거나 라인의 이전 서브 프로세스 객체의 stdout 속성을 사용하여 직접 더 붙일 수 있지만 실제로는 없습니다 이 특별한 경우에는 파이썬에서 직접 쉽게 코딩 할 수 있기 때문에 그 이유가 있습니다. 예 :

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

나는 이것이 정답이라고 생각할 것이다. OP가 물었던 것과 정확히 어떻게 대답했는지, 그리고 어떻게 해결할 수 있는지에 대해 가르치고 있지는 않다. – Beli

관련 문제