如何使用Python的 PIL模块将EXIF数据写入JPG文件?

编程语言 2026-07-11

在Ubuntu 20.04的 Python 3.8环境中,使用PIL.Image版本7.0.0时,我在将EXIF数据写入新文件的过程中遇到了问题。
我尝试使用(可能略作修改的)EXIF数据(即标签306 “DateTime”)来写入一个新的jpg文件。然而从新文件中读取EXIF数据时,显然存在问题,数据被明显错误地填充。见下文:

原始标签:

36867 : DateTimeOriginal            : 2003:01:12 03:04:15
36868 : DateTimeDigitized           : 2003:01:12 03:04:15
  306 : DateTime                    : 2003:01:12 03:04:15

新文件的标签(使用未修改的EXIF数据):

36867 : DateTimeOriginal            : 3:04:152003:01:12 0
36868 : DateTimeDigitized           : 3:04:152003:01:12 0
  306 : DateTime                    : ´2003:01:12 0

可以看到标签306缺失的尾部 '3:04:14' 出现在其他标签的前缀中。这种行为在来自不同来源的JPEG文件中都会出现。

我使用的完整测试代码如下:

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

def fingerExifAndSave(source,target):
    im=PIL.Image.open(source)  
    imexif=im.getexif()

    if False :  # False True
        print("Change tag 306 (DateTime) to something wired for debugging")
        imexif[306] = 'abcdefghijklmnopqrs'     # tag 306 means "DateTime"
        imexif[306] = '2066:55:44 33:22:11'   
        print("   Tag 306 is now set to :",imexif[306] )
    else: 
        print("NO MODIFICATION TO TAG 306 ('DateTime')!") 

    # Due to "/usr/lib/p*3/dist*/PIL/TiffImagePlugin.py:588: UserWarning: \
    #     Metadata Warning, tag 282 had too many entries: 2, expected 1 "
    if False :  # False True
        print("Repairing something for some unknown reason due to warning")
        for r in (282,283):  imexif[r]= imexif[r][0]
    else:
        print("NO REAPIRING TO TAGS (282,283)!")    

    rc=im.save(target, exif=imexif) # Save using the optionally modified EXIF
    print("Image written to:",target,"  with rc =",rc )
    im.close()
    imexif=None

def showSomeExifTags(myfile):
    showThisTags=[306,36867,36868,305]  # 'DateTime'-entries and 'Software'
    im=PIL.Image.open(myfile)  
    imexif=im.getexif()
    print("\nSome EXIF-tags from '"+myfile+"' (among other):")
    print("KeyNr : KeyName"+" "*21+": Value")
    for k,v in imexif.items():
        if k in showThisTags:
            if len(str(v)) > 30 : v=str(v[0:20])+"..."  # keep it smooth
            print(f"{k:>5} : {PIL.ExifTags.TAGS[k]:27} : {v}")
    im.close()
    print()

def main():
    source="./orig2.jpg"   # "./orig2.jpg"
    target="./modified.jpg"
    print ("PIL.Image.__version__  in use:",PIL.Image.__version__) 
    showSomeExifTags(source)
    fingerExifAndSave(source,target)
    showSomeExifTags(target)

if __name__ == "__main__":
    main()

我是不是做错了什么?如果是,应该如何正确地做?

在网上搜索时,是否有我错过的已知漏洞?

如何绕过这个问题?

解决方案

我在基于Ubuntu 24.04的 Linux Mint 22上,用不同的 pillow 版本进行了测试。
Python 3.8.20

  • 7.0.07.1.07.1.17.1.2 —— 也会出现同样的问题。
  • 7.2.08.0.0 —— 可以正常工作。

你需要将模块更新到 7.2.0

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章