piexif.load() 报 InvalidImageDataError 时,先用 exiftool -v1 检查 Exif 可读性;若失败则用 PIL 重保存修复结构,若成功则加 strict=False 参数绕过校验。

piexif.load() 报 InvalidImageDataError 怎么办
不是所有 JPG 文件都真正符合 JPEG 标准,尤其手机直出或微信转发过的图,Exif 段可能损坏或位置异常。piexif 会严格校验,直接抛错,而不是跳过。
- 先用
exiftool -v1 image.jpg看 Exif 是否可读(命令行工具比 Python 库更宽容) - 若 exiftool 也报错,说明文件本身有问题,别硬塞给
piexif.load()—— 先用 PIL 打开再保存一次可修复基础结构:from PIL import Image<br>img = Image.open("bad.jpg")<br>img.save("fixed.jpg", "JPEG", quality=95) - 若 exiftool 能读但 piexif 不行,大概率是 Exif 头在 JPEG 中的位置偏移异常;加
strict=False参数绕过部分校验:piexif.load(data, strict=False)
修改 DateTimeOriginal 时,为什么照片在 Windows 资源管理器里时间没变
Windows 资源管理器默认显示的是文件系统“最后修改时间”(mtime),不是 Exif 里的 DateTimeOriginal。两者完全独立,改了 Exif 不等于改了文件时间戳。
- Exif 时间只影响相册软件、Lightroom、手机图库等读取元数据的程序
- 要同步更新文件时间,得额外调用
os.utime():import os<br>os.utime("photo.jpg", (stat.st_atime, exif_timestamp)),其中exif_timestamp需从"2023:05:12 14:30:22"格式转成秒级时间戳 - 注意:iOS 照片导出后常把
DateTimeOriginal写进Exif IFD,但 Windows Explorer 只认GPS IFD或文件头时间 —— 别指望它显示对
批量写入 GPS 坐标,piexif.dump() 后照片打不开
GPS 坐标必须按 Exif 规范以有理数(piexif.Rational)形式写入,且纬度/经度需拆成度分秒三组整数 + 分母。直接塞浮点数或字符串会破坏二进制结构,导致图片损坏。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 正确做法:用
piexif.helper.set_gps_location()辅助函数,它自动处理格式转换:piexif.helper.set_gps_location(exif_dict, lat, lng, alt=0) - 手动构造时,必须确保
GPSLatitude是形如((39,1), (57,1), (2253,100))的 tuple,不能是[39.95625] - 写入前务必检查
exif_dict["GPS"]是 dict 类型,空值要用{}占位,不能是None或缺失键 - 写完立刻用
exiftool photo.jpg -gps:all验证,别等批量跑完才发现全错了
中文作者名、拍摄地写进 Exif 后乱码或被截断
Exif 标准只定义了 ASCII 和 JIS(日文)编码,piexif 默认用 ASCII 存字符串。中文必须显式指定 UTF-8 编码,并写入 ExifUserComment 字段(该字段支持编码标识),其他字段如 Artist 或 ImageDescription 强制 ASCII 会丢字。
立即学习“Python免费学习笔记(深入)”;
- 写中文作者名:用
ExifUserComment,并带上 UTF-8 BOM 标识:user_comment = b"\x45\x78\x69\x66\x00\x00\x00\x00" + "张三".encode("utf-8")<br>exif_dict["Exif"][piexif.ExifIFD.UserComment] = user_comment - 避免用
ImageDescription存中文 —— piexif 会静默截断或替换成 ? - 如果目标平台是手机相册,优先写
XPAuthor(Windows 属性字段),它原生支持 Unicode:exif_dict["0th"][piexif.ImageIFD.XPAuthor] = "张三".encode("utf-16-le")

















