从python脚本调用exiftool吗? [英] Call exiftool from a python script?

查看:297
本文介绍了从python脚本调用exiftool吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望使用exiftool扫描照片和视频中的EXIF标签.这是一个perl可执行文件.以此推断的最佳方法是什么?是否已经有Python库可以执行此操作?还是应该直接调用可执行文件并解析输出? (后者似乎很脏.)谢谢.

I'm looking to use exiftool to scan the EXIF tags from my photos and videos. It's a perl executable. What's the best way to inferface with this? Are there any Python libraries to do this already? Or should I directly call the executable and parse the output? (The latter seems dirty.) Thanks.

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

The reason I ask is this because I am currently using pyexiv2, which does not have support for videos. Perl's exiftool has very broad support for images and videos, and I'd like to use it.

推荐答案

为避免为每个图像启动新进程,应使用

To avoid launching a new process for each image, you should start exiftool using the -stay_open flag. You can then send commands to the process via stdin, and read the output on stdout. ExifTool supports JSON output, which is probably the best option for reading the metadata.

这是一个简单的类,它启动一个exiftool进程,并具有一个execute()方法向该进程发送命令.我还提供了get_metadata()来读取JSON格式的元数据:

Here's a simple class that launches an exiftool process and features an execute() method to send commands to that process. I also included get_metadata() to read the metadata in JSON format:

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))

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

This class is written as a context manager to ensure the process is exited if you are done. You can use it as

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

编辑python 3: 为了使它在python 3中工作,需要做两个小改动.第一个是subprocess.Popen的附加参数:

EDIT for python 3: To get this to work in python 3 two small changes are needed. The first is an additional argument to subprocess.Popen:

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

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

The second is that you have to decode the byte series returned by os.read():

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

针对Windows的要使其在Windows上正常运行,必须将sentinel更改为"{ready}\r\n",即

EDIT for Windows: To get this working on Windows, the sentinel need to be changed into "{ready}\r\n", i.e.

sentinel = "{ready}\r\n"

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

Otherwise the program will hang because the while loop inside execute() won't stop

这篇关于从python脚本调用exiftool吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆