使用imageio生成PNG时出现‘Image’无‘fp’属性错误求助
关于imageio写入PNG时的错误与警告分析
首先还原你的代码场景:
import numpy as np import matplotlib.cm as cm import imageio # for saving the image import matplotlib as mpl hm_colors = ['blue', 'white','red'] cmap = mpl.colors.LinearSegmentedColormap.from_list('bwr', hm_colors) data = np.array([[1,2,3],[5,6,7]]) norm = mpl.colors.Normalize(vmin=-3, vmax=3) colormap = cm.ScalarMappable(norm=norm, cmap=cmap) im = colormap.to_rgba(data) # scale the data to a width of w pixels im = np.repeat(im, w, axis=1) im = np.repeat(im, h, axis=0) # save the picture imageio.imwrite("my_img.png", im)
你遇到的情况是:自动运行时弹出Error closing: 'Image' object has no attribute 'fp'错误,还有一条浮点数转uint8的警告,但图片居然能正常生成保存,而且没法稳定复现这个错误,怀疑和Celery有关。咱们逐个拆解问题:
先解释那个“Lossy conversion”警告
这条警告完全是正常提示,不用过度担心:
- 你的
im变量是float64类型数组,像素值范围在[0,1]之间(to_rgba输出的就是0-1的浮点数)。 - 而PNG图片存储的是
uint8类型像素值(0-255),imageio会自动帮你把0-1的浮点数缩放成0-255的整数。这个转换确实会损失一点点精度,但对图片视觉效果几乎没有影响,所以图片能正常生成。
再聊聊那个“Error closing”错误
这个错误的根源大概率和Celery的异步多进程环境有关:
- 虽然你没直接用PIL,但imageio底层其实依赖了Pillow(PIL的分支)处理PNG文件。调用
imwrite时,imageio会创建一个Pillow的Image对象写入文件,写完后会尝试关闭关联的文件指针(fp)。 - Celery的worker进程是独立调度的,任务执行完毕后,进程资源可能会被快速回收或者在进程间出现资源共享混乱。这就导致当imageio去关闭那个Image对象的
fp时,这个属性已经被提前销毁或者找不到了,于是抛出错误。 - 为什么没影响图片结果?因为核心的文件写入操作已经完成了!这个错误发生在写入后的资源清理阶段,图片数据已经完整写入磁盘,只是后续的资源释放步骤出了问题,所以最终的图片是正常的。
一些验证和解决建议
- 显式指定imageio的插件后端,避免底层自动选择带来的资源问题:
imageio.imwrite("my_img.png", im, plugin="pillow") - 在Celery任务中手动管理资源,比如用
with语句包装文件操作(或者直接用Pillow写入,绕开imageio的底层调用):from PIL import Image # 把float数组转成uint8 im_uint8 = (im * 255).astype(np.uint8) with Image.fromarray(im_uint8) as img: img.save("my_img.png") - 这个错误是异步环境下的偶发资源冲突,所以你没法稳定复现也很正常——只有当Celery的进程调度刚好触发资源回收时机和imageio的清理步骤重叠时,才会出现这个错误。
内容的提问来源于stack exchange,提问作者Liis Kolberg
相关产品推荐
相关产品推荐

