推荐用 exifread 替代 pillow 读取 exif,因其对非标准 jpeg 兼容性好、跳过损坏字段不中断;需二进制打开、设 details=false 加速;须过滤非图像文件、捕获异常;gps 坐标需手动解析 rational 并处理符号。

直接用 Pillow 就能批量读取,但别用 Image._getexif() —— 它返回 None 的概率太高,尤其遇到 WebP、HEIC 或带编辑历史的 JPEG。
用 exifread 替代 Pillow 读取更稳定
exifread 是纯 Python 实现,不依赖 PIL 解码逻辑,对非标准 JPEG(比如手机直出带厂商私有标签的图)兼容性好得多。它默认跳过损坏字段,不会像 Pillow 那样因一个 tag 报错就中断整个文件。
- 安装:
pip install exifread - 读取时用二进制打开:
open(filepath, 'rb'),不是'r' - 关键参数加
details=False可显著提速(跳过冗余解析),多数场景够用 - 注意:不支持 WebP 和 HEIC,遇到这类格式会静默失败,需提前过滤或换库
批量处理时必须跳过非图像文件和权限异常
实际目录里常混着 .DS_Store、.thumb、临时缩略图,os.listdir() 或 glob 拿到路径后不校验直接 open,十次有八次报 IOError 或 OSError。
- 用
imghdr.what(filepath)做轻量检测,比靠扩展名靠谱(有些 PNG 改名成 .jpg) - 捕获
PermissionError和IsADirectoryError,跳过而非中断 - 对空文件或 0 字节文件,
exifread会抛KeyError,建议加try/except KeyError吞掉
提取 GPS 坐标要手动解析有理数(Rational)
EXIF 里的经纬度存的是 Rational 类型(分子/分母形式),不是浮点数。直接 print 会看到类似 (401234567, 10000000),得自己转成小数。
- 用
float(rat.num) / float(rat.den)计算,别用float(rat)—— 某些版本会报TypeError - 方向标签(
GPSInfo.GPSLatitudeRef)决定正负:'S' 或 'W' 要加负号 - 很多手机图根本没写 GPS,
GPSInfo字段可能完全缺失,检查前先用if 'GPSInfo' in tags:
真正麻烦的不是读取,是不同相机厂商往 EXIF 里塞私有 tag 的方式五花八门——有的用 ASCII 字符串,有的用嵌套 IFD,有的甚至把 JSON 打包进 UserComment。真要全兼容,得准备 fallback 到 piexif 或 exiftool 子进程调用。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











