Python提取照片Exif数据异常:Mac显示有元数据但部分照片Exif字典为空的原因排查
问题分析与解决方案
我之前也碰到过一模一样的情况,结合你的场景和代码,咱们来拆解下背后的原因:
核心矛盾:元数据存储位置 + PIL的读取局限
- Google Photos的导出特殊处理:那5%的照片从Google Photos下载后,拍摄日期等元数据并没有存在传统的Exif数据块里,而是被转移到了XMP元数据或者Mac系统维护的Spotlight索引中。Google Photos有时候为了压缩效率或格式兼容性,会把元数据放到这些非标准Exif的位置。
- Mac显示元数据的“多源”特性:Mac的「显示简介」里的拍摄日期,并不只依赖Exif。它会优先读Exif,没有的话就去读XMP、IPTC,甚至直接用文件的创建/修改时间(Google Photos导出时经常会把拍摄日期同步成文件时间),或者调用Spotlight的数据库数据——所以你能看到,但脚本读不到。
- PIL的
getexif()能力边界:你用的Pillow(PIL)的getexif()方法,只专注于读取JPEG/PNG等格式里的传统Exif区块,对XMP、HEIC格式的元数据支持很差。如果元数据存在其他位置,它自然返回空字典。
验证与解决办法
1. 先确认照片格式
先检查那部分异常照片是不是HEIC格式?Mac原生支持HEIC,但Pillow默认不支持读取HEIC的Exif。如果是HEIC,先安装适配库:
pip install pillow-heif
再修改代码:
from pillow_heif import register_heif_opener from PIL import Image from PIL.ExifTags import TAGS # 注册HEIC格式支持 register_heif_opener() my_img = Image.open("one.heic") exif_data = my_img.getexif() for tagId in exif_data: tag = TAGS.get(tagId, tagId) data = exif_data.get(tagId) print(f"{tag:16}: {data}")
2. 读取XMP元数据
如果是JPG但元数据存在XMP里,换用exifread库,它能读取更多元数据格式:
pip install exifread
代码示例:
import exifread with open("one.jpg", 'rb') as f: tags = exifread.process_file(f, details=True) # 过滤掉无关的缩略图等标签 for tag in tags.keys(): if tag not in ['JPEGThumbnail', 'TIFFThumbnail', 'Filename', 'EXIF MakerNote']: print(f"{tag:25}: {tags[tag]}")
这个库会扫描包括XMP在内的多种元数据区域,大概率能找到你要的拍摄日期。
3. 退而求其次:读取文件属性
如果以上方法都不行,那Mac显示的日期大概率是文件的创建/修改时间,用Python直接读取:
import os from datetime import datetime file_stats = os.stat("one.jpg") print("文件创建时间(对应拍摄日期):", datetime.fromtimestamp(file_stats.st_birthtime)) print("文件修改时间:", datetime.fromtimestamp(file_stats.st_mtime))
Google Photos导出时经常会把拍摄日期同步为文件的创建时间,这也能作为备选方案。
内容的提问来源于stack exchange,提问作者RickRugby




