You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu 20.04环境下Python 3.8搭配PIL 7.0.0写入JPG文件EXIF数据时出现数据错位问题的求助

问题分析与解决方案

先给你吃个定心丸:这真不是你的操作错误,而是Pillow 7.0.0版本中存在的已知EXIF写入bug,不少用户都反馈过类似的EXIF字符串错位、填充错误问题。根源在于旧版本的TiffImagePlugin.py处理EXIF字符串时的字节对齐逻辑有缺陷,导致写入时字符串内容被错误截断或拼接,才出现了你看到的标签内容“串位”情况。

解决方法

1. 优先升级Pillow版本

这个bug在Pillow 8.0.0及以后的版本中已经被官方修复,最简单直接的解决方式就是升级你的Pillow库:

# 如果你用的是系统自带的Python,建议加--user避免权限冲突
pip install --upgrade pillow --user
# 要是用了虚拟环境,直接运行下面这句就行
pip install --upgrade pillow

升级完成后再跑你的测试代码,EXIF数据写入就会恢复正常,不会再出现内容错位的问题。

2. 临时替代方案(无法升级时)

如果因为环境限制没法升级Pillow,可以换用piexif库来处理EXIF数据,它的EXIF读写逻辑更稳定可靠。我把你的代码修改成用piexif实现的版本,你可以直接参考:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import PIL.Image
import piexif

def fingerExifAndSave(source,target):
    im=PIL.Image.open(source)
    # 用piexif读取EXIF数据为字典格式
    exif_dict = piexif.load(im.info["exif"])
    
    if False : # 改成True可以测试修改标签
        print("Change tag 306 (DateTime) to something wired for debugging")
        # DateTime在EXIF的0th组中,用piexif的常量来定位标签
        exif_dict["0th"][piexif.ImageIFD.DateTime] = '2066:55:44 33:22:11'
        print(" Tag 306 is now set to :",exif_dict["0th"][piexif.ImageIFD.DateTime] )
    else:
        print("NO MODIFICATION TO TAG 306 ('DateTime')!")
    
    # 修复282/283标签的问题(如果需要)
    if False : # 改成True启用修复
        print("Repairing something for some unknown reason due to warning")
        for tag in (piexif.ImageIFD.XResolution, piexif.ImageIFD.YResolution):
            if isinstance(exif_dict["0th"][tag], tuple):
                exif_dict["0th"][tag] = exif_dict["0th"][tag][0]
    else:
        print("NO REAPIRING TO TAGS (282,283)!")
    
    # 将EXIF字典转为字节流,供保存时使用
    exif_bytes = piexif.dump(exif_dict)
    rc=im.save(target, exif=exif_bytes) 
    print("Image written to:",target," with rc =",rc )
    im.close()

def showSomeExifTags(myfile):
    showThisTags=[306,36867,36868,305] # 要展示的标签编号
    im=PIL.Image.open(myfile)
    # 读取EXIF,没有的话用空字节流
    exif_dict = piexif.load(im.info.get("exif", b""))
    print("\nSome EXIF-tags from '"+myfile+"' (among other):")
    print("KeyNr : KeyName"+" "*21+": Value")
    
    # 遍历0th和Exif两个组的标签
    for ifd_name in ["0th", "Exif"]:
        for k,v in exif_dict[ifd_name].items():
            if k in showThisTags:
                # 获取标签名称
                if ifd_name == "0th":
                    tag_name = piexif.ImageIFD.get(k, str(k))
                else:
                    tag_name = piexif.ExifIFD.get(k, str(k))
                if len(str(v)) > 30 :
                    v=str(v[0:20])+"..." # 过长内容截断显示
                print(f"{k:>5} : {tag_name:27} : {v}")
    im.close()
    print()

def main():
    source="./orig2.jpg" # 源图片路径
    target="./modified.jpg" # 目标图片路径
    print ("PIL.Image.__version__ in use:",PIL.Image.__version__)
    print ("piexif version in use:", piexif.VERSION)
    showSomeExifTags(source)
    fingerExifAndSave(source,target)
    showSomeExifTags(target)

if __name__ == "__main__":
    main()

使用前需要先安装piexif:

pip install piexif --user

验证

不管是升级Pillow还是用piexif替代,重新运行代码后,新文件里的EXIF标签都会和原始内容完全一致,不会再出现内容错位的情况。

内容的提问来源于stack exchange,提问作者Feiler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 09:37:40