IFDRational 不可使用 Pillow 进行 JSON 序列化

问题描述 投票:0回答:1

我正在 python 中使用 PIL 来提取图像的元数据。

这是我的代码:

import json
from PIL import Image, TiffImagePlugin
import PIL.ExifTags

img = Image.open("/home/user/DSCN0010.jpg")

dct = {
        PIL.ExifTags.TAGS[k]: float(v) if isinstance(v, TiffImagePlugin.IFDRational) else v
        for k, v in img._getexif().items()
        if k in PIL.ExifTags.TAGS
    }

print(json.dumps(dct))

我收到以下错误:

Error processing EXIF data: Object of type IFDRational is not JSON serializable

正如您在代码中看到的,我将

IFDRational
类型的所有值都转换为
float
但我仍然收到错误。

这是图像的链接:https://github.com/ianare/exif-samples/blob/master/jpg/gps/DSCN0010.jpg

python json python-imaging-library metadata
1个回答
0
投票

问题是您只是将float转换为直接位于EXIF项根中的

IFDRational
值。但是,看起来
GPSInfo
数据是一个
dict
,内部包含更多
IFDRational
值。
您需要一个函数来清理这些值,理想情况下,该函数会递归地迭代所有可能的嵌套数据,以便在所有级别上完成转换。

最初的想法是这样做:

import json import PIL.ExifTags from PIL import Image, TiffImagePlugin img = Image.open("/home/user/DSCN0010.jpg") def sanitise_value(value): # Base case: IFDRational to float if isinstance(value, TiffImagePlugin.IFDRational): return float(value) # Dict case: sanitise all values if isinstance(value, dict): for k, v in value.items(): value[k] = sanitise_value(v) # List/tuple case: sanitise all values and convert to list, # as a tuple in JSON will anyway be a list elif isinstance(value, (list, tuple)): value = [sanitise_value(i) for i in value] # Extra case: some values are byte-strings, so you have to # decode them in order to make them JSON serializable. I # decided to use 'replace' in case some bytes cannot be # decoded, but there are other options elif isinstance(value, (bytes, bytearray)): value = value.decode("utf-8", "replace") return value dct = { PIL.ExifTags.TAGS[k]: sanitise_value(v) # <-- We use here the sanitising function for k, v in img._getexif().items() if k in PIL.ExifTags.TAGS } print(json.dumps(dct))

这适用于该图像,但请随意测试其他场景,以防万一它仍然不是通用解决方案。

另外,请记住有关

byte-strings

的评论,因为您可能需要根据您的需要以不同的方式对它们进行解码。 例如,您可能更愿意将其解码为

latin-1
而不是
utf-8
,或者使用
此处
所述的其他类型的错误处理。 希望这有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.