为避免为每个图像启动新进程,应开始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))
此类被编写为上下文管理器,以确保完成后退出该过程。您可以将其用作
with ExifTool() as e:
Metadata = e.get_Metadata(*filenames)
编辑python 3:要使其在python 3中工作,需要进行两个小的更改。第一个是subprocess.Popen
:
self.process = subprocess.Popen(
[self.executable, "-stay_open", "True", "-@", "-"],
universal_newlines=True,
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
第二个是您必须解码由返回的字节序列os.read()
:
output += os.read(fd, 4096).decode('utf-8')
Windows的EDIT:要在Windows上运行,sentinel
需要将其更改为"{ready}\r\n"
,即
sentinel = "{ready}\r\n"
否则程序会挂起,因为execute()中的while循环不会停止