2012-04-09 51 views
5

Estoy buscando usar exiftool para escanear las etiquetas EXIF ​​de mis fotos y videos. Es un ejecutable perl. ¿Cuál es la mejor manera de inferfar con esto? ¿Ya hay alguna biblioteca de Python para hacer esto? ¿O debería llamar directamente al ejecutable y analizar el resultado? (Este último parece sucio.) Gracias.¿Llamar a exiftool desde un script python?

La razón por la que pregunto es porque actualmente estoy usando pyexiv2, que no admite videos. Exiftool de Perl tiene un amplio soporte para imágenes y videos, y me gustaría usarlo.

+1

usted debe leer la documentación del módulo suprocess: http://docs.python.org/library/subprocess.html – mandel

+1

He cargado una versión más completa del código en mi respuesta a https://github.com/smarnach/pyexiftool. –

Respuesta

18

Para evitar iniciar un nuevo proceso para cada imagen, debe comenzar exiftool usando la bandera -stay_open. A continuación, puede enviar comandos al proceso mediante stdin y leer la salida en stdout. ExifTool admite salida JSON, que es probablemente la mejor opción para leer los metadatos.

Aquí hay una clase simple que inicia un proceso exiftool y presenta un método execute() para enviar comandos a ese proceso. También incluí get_metadata() para leer los metadatos en formato 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)) 

Esta clase está escrita como un gestor de contexto para asegurar que el proceso se sale si ha terminado. Se puede utilizar como

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

EDITAR para Python 3: Para conseguir que esto funcione en Python se necesitan 3 dos pequeños cambios. El primero es un argumento adicional para subprocess.Popen:

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

La segunda es que hay que decodificar la serie de bytes devuelto por os.read():

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

Gracias, esto fue muy útil. ¿Cómo pasaría los comandos a exiftool para que el ejecutable "permanezca abierto?" Si pongo el ejecutable en una función llamada parseImage(), ¿no se volvería a abrir cada vez que se llama a la función? – ensnare

+0

@ensnare: Incluí un poco de código. Mejoraré el código en unas pocas minutas. –

+0

Sí, esto es genial. Muchas gracias. – ensnare

Cuestiones relacionadas