2010-03-22 42 views
13

Tôi đang cố gắng sử dụng subprocess.Popen để tạo chuỗi để lấy thời lượng của tệp video. Tôi đã tìm kiếm trong 3 ngày, và không thể tìm thấy bất cứ lý do trực tuyến là tại sao mã này không hoạt động, nhưng nó giữ cho tôi một kết quả trống:Sử dụng đúng subprocess.PIPE trong 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

Tại sao bạn đang sử dụng grep, cắt và sed để phân tích đầu ra thay vì sử dụng các chức năng Python BUILTIN? –

+1

[subprocess.PIPE] (http://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/) là kẻ thù của bạn – ldgorman

Trả lời

14

stderr cần được chuyển hướng đến chế độ xuất chuẩn. Ngoài ra, có không cần phải gọi cho công cụ khác như cut/sed vv làm thao tác chuỗi của bạn bằng 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] 

Nếu Python không là điều bắt buộc, bạn có thể sử dụng trực tiếp vỏ.

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

Cảm ơn bạn. Tôi đã không nhận ra tôi đã phải chuyển hướng 'stderr' là tốt. –

13

Sử dụng subprocess.PIPE sẽ không kỳ diệu dây các đúng ống cho bạn.

Bạn phải vượt qua đường ống đầu ra của quy trình đầu tiên làm giá trị cho tham số stdin của quy trình thứ hai. See the docs for an example.

4

Python không thể "xây dựng toàn bộ đường ống" theo cách này - nó có thể ủy quyền nhiệm vụ cho trình bao, hoặc dán trực tiếp lên bằng cách sử dụng thuộc tính stdout của các đối tượng con trước đó trong dòng, nhưng thực sự không có lý do cho điều đó trong trường hợp cụ thể này, vì bạn có thể mã nó trực tiếp bằng Python khá dễ dàng. Ví dụ:

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

Như những người khác đã chỉ ra, bạn cần phải chuyển PIPE từ quy trình này sang quy trình tiếp theo. Giá trị chuẩn (PIPE) từ một quy trình trở thành tiêu chuẩn cho tác vụ sau.

Something như thế này (bắt đầu từ ví dụ của bạn):

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

Tôi xem đây là câu trả lời đúng, nó trả lời chính xác những gì OP hỏi và không hướng dẫn cách bạn có thể làm việc xung quanh nó. – Beli

Các vấn đề liên quan