2012-04-09 36 views
5

Tôi đang tìm cách sử dụng exiftool để quét thẻ EXIF ​​từ ảnh và video của mình. Đó là một thực thi perl. Cách tốt nhất để inferface với điều này là gì? Có thư viện Python nào để làm điều này không? Hoặc tôi nên trực tiếp gọi thực thi và phân tích đầu ra? (Sau này có vẻ bẩn.) Cảm ơn.Gọi exiftool từ tập lệnh python?

Lý do tôi hỏi là vì tôi hiện đang sử dụng pyexiv2, không hỗ trợ video. Perl's exiftool có hỗ trợ rất rộng cho hình ảnh và video, và tôi muốn sử dụng nó.

+1

Bạn nên đọc các tài liệu của các mô-đun suprocess: http://docs.python.org/library/subprocess.html – mandel

+1

Tôi đã tải lên phiên bản hoàn chỉnh hơn của mã trong câu trả lời của mình cho https://github.com/smarnach/pyexiftool. –

Trả lời

18

Để tránh khởi chạy quy trình mới cho từng hình ảnh, bạn nên bắt đầu exiftool bằng cờ -stay_open. Sau đó bạn có thể gửi lệnh cho quá trình thông qua stdin, và đọc đầu ra trên stdout. ExifTool hỗ trợ đầu ra JSON, có lẽ là tùy chọn tốt nhất để đọc siêu dữ liệu.

Đây là một lớp đơn giản khởi chạy quy trình exiftool và có phương thức execute() để gửi lệnh đến quy trình đó. Tôi cũng bao gồm get_metadata() để đọc các siêu dữ liệu ở định dạng JSON:

import subprocess 
import os 
import json 

class ExifTool(object): 

    sentinel = "{ready}\n" 

    def __init__(self, executable="/usr/bin/exiftool"): 
     self.executable = executable 

    def __enter__(self): 
     self.process = subprocess.Popen(
      [self.executable, "-stay_open", "True", "[email protected]", "-"], 
      stdin=subprocess.PIPE, stdout=subprocess.PIPE) 
     return self 

    def __exit__(self, exc_type, exc_value, traceback): 
     self.process.stdin.write("-stay_open\nFalse\n") 
     self.process.stdin.flush() 

    def execute(self, *args): 
     args = args + ("-execute\n",) 
     self.process.stdin.write(str.join("\n", args)) 
     self.process.stdin.flush() 
     output = "" 
     fd = self.process.stdout.fileno() 
     while not output.endswith(self.sentinel): 
      output += os.read(fd, 4096) 
     return output[:-len(self.sentinel)] 

    def get_metadata(self, *filenames): 
     return json.loads(self.execute("-G", "-j", "-n", *filenames)) 

Lớp này được viết như một người quản lý bối cảnh để đảm bảo quá trình được thoát nếu bạn đang thực hiện. Bạn có thể sử dụng nó như

with ExifTool() as e: 
    metadata = e.get_metadata(*filenames) 

EDIT cho python 3: Để có được điều này để làm việc trong python 3 hai thay đổi nhỏ là cần thiết. Đầu tiên là một cuộc tranh cãi bổ sung cho subprocess.Popen:

self.process = subprocess.Popen(
     [self.executable, "-stay_open", "True", "[email protected]", "-"], 
     universal_newlines=True, 
     stdin=subprocess.PIPE, stdout=subprocess.PIPE) 

Thứ hai là bạn phải giải mã loạt byte trả về bởi os.read():

output += os.read(fd, 4096).decode('utf-8') 
+0

Cảm ơn, điều này rất hữu ích. Làm thế nào tôi sẽ vượt qua các lệnh để exiftool để thực thi "vẫn mở?" Nếu tôi đặt thực thi trong một hàm được gọi là parseImage(), nó sẽ không mở lại mỗi khi hàm được gọi? – ensnare

+0

@ensnare: Tôi đã bao gồm một chút mã. Tôi sẽ cải thiện mã trong vài phút. –

+0

Yup, điều này thật tuyệt. Cám ơn rất nhiều. – ensnare

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