Python Tkinter使用PIL保存图片时PhotoImage无save属性错误如何解决
错误诱因
报错的核心原因有两个:
- 类型不匹配:
save()是PIL库Image对象的专属方法,你在fileSave函数中把self.img赋值为self.image_image_3,后者是Tkinter的PhotoImage类型,本身没有save方法,调用后直接触发AttributeError。 - 赋值逻辑错误:
fileOpen函数执行时已经把用户选择的原始图片以PILImage类型存入了self.img变量,但fileSave中强行覆盖了这个变量,直接丢失了可正常执行保存操作的图片对象。另外你代码中赋值的self.image_image_3是页面初始化时的静态占位图,和用户打开的待保存图片没有关联。
修复方案
根据保存需求分为两种场景,按需选择即可:
场景1:保存用户打开的原始图片
直接修改fileSave函数逻辑,去掉错误的变量覆盖代码,同时将文件保存模式调整为二进制模式避免图片损坏,修改后代码如下:
def fileSave(self): # 直接使用fileOpen中已经赋值的PIL Image类型的self.img,不要覆盖 filename = filedialog.asksaveasfilename( title='选择保存路径', defaultextension=".png", filetypes=[ ( "图片文件",("*.jpg","*.bmp", "*.jpeg", "*.png", "*.gif") ), ("所有文件", ("*.*"))] ) if filename: self.img.save(filename)
场景2:保存界面上显示的、经过resize处理后的图片
你在fileOpen中已经把resize后的图片存入了self.resized_image实例变量,直接调用这个变量的save方法即可:
def fileSave(self): filename = filedialog.asksaveasfilename( title='选择保存路径', defaultextension=".png", filetypes=[ ( "图片文件",("*.jpg","*.bmp", "*.jpeg", "*.png", "*.gif") ), ("所有文件", ("*.*"))] ) if filename: self.resized_image.save(filename)
补充说明
如果你坚持使用asksaveasfile而非asksaveasfilename,需要将打开模式改为wb(二进制写入),操作完成后手动关闭文件对象,避免资源泄漏:
def fileSave(self): file = filedialog.asksaveasfile( mode='wb', title='选择保存路径', defaultextension=".png", filetypes=[ ( "图片文件",("*.jpg","*.bmp", "*.jpeg", "*.png", "*.gif") ), ("所有文件", ("*.*"))] ) if file: self.img.save(file) file.close()
修改后即可支持PNG、BMP、JPG等多种格式的导出,PIL会根据你选择的文件后缀自动适配编码格式。
内容的提问来源于stack exchange,提问作者AlvaroSt
相关产品推荐
相关产品推荐

