从python脚本调用exiftool?

ens*_*are 7 python exiftool

我希望使用exiftool扫描我的照片和视频中的EXIF标签.这是一个perl可执行文件.用这个来表达最好的方法是什么?有没有Python库可以做到这一点?或者我应该直接调用可执行文件并解析输出?(后者看起来很脏.)谢谢.

我问的原因是因为我目前正在使用pyexiv2,它不支持视频.Perl的exiftool对图像和视频有非常广泛的支持,我想使用它.

Sve*_*ach 23

为避免为每个图像启动新进程,您应该开始exiftool使用该-stay_open标志.然后,您可以通过stdin将命令发送到进程,并读取stdout上的输出.ExifTool支持JSON输出,这可能是读取元数据的最佳选择.

这是一个简单的类,它启动一个exiftool进程,并提供一个execute()向该进程发送命令的方法.我还包括get_metadata()以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",  "-@", "-"],
            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))
Run Code Online (Sandbox Code Playgroud)

此类被编写为上下文管理器,以确保在您完成后退出该过程.你可以用它作为

with ExifTool() as e:
    metadata = e.get_metadata(*filenames)
Run Code Online (Sandbox Code Playgroud)

编辑python 3:为了让它在python 3中工作,需要进行两处小改动.第一个是另外一个论点subprocess.Popen:

self.process = subprocess.Popen(
         [self.executable, "-stay_open", "True",  "-@", "-"],
         universal_newlines=True,
         stdin=subprocess.PIPE, stdout=subprocess.PIPE)
Run Code Online (Sandbox Code Playgroud)

第二个是你必须解码返回的字节序列os.read():

output += os.read(fd, 4096).decode('utf-8')
Run Code Online (Sandbox Code Playgroud)

EDIT for Windows:要在Windows上运行,sentinel需要更改为"{ready}\r\n",即

sentinel = "{ready}\r\n"
Run Code Online (Sandbox Code Playgroud)

否则程序将挂起,因为execute()内的while循环不会停止