忽略 python 中 libpng 的 iCCP 警告

问题描述

在使用 Python 处理 PNG 图片时,经常会遇到以下警告:

libpng warning: iCCP: known incorrect sRGB profile

根据 libpng 官方的说法, 图片本来就是坏的, 但是 libpng 仍然会尝试去处理它, 导致这个警告.

但即使项目中没有用任何 png 图片素材, 仅仅用 Tkinter 创建一个窗口都会触发一大堆这个警告刷屏, 强迫症患者震怒.

libpng_warnings

而且这个错误是直接调用 c 函数输出的, 十分恶心.

尝试过程

网上看了一堆垃圾教程, 没一个有用的. 总结一下这些垃圾教程教的方法:

  • 使用 warning 库屏蔽输出.
    不可能有用, warning 库只能做到 python 层面屏蔽, 输出都不经过 python.
  • 重定向 stderr.
    python 内置的 sys.stderr 本质还是经过 python 包装过的, 无法重定向 c 的输出.

解决方法

还是重定向 stderr 输出管道, 并不优雅, 但至少没有一堆警告刷屏了.

与直接用sts.stderr = open(os.devnull, 'w') 不同, 这里需要更底层的操作.

这里实现一个上下文管理器, 在进入时重定向 stderr, 离开时恢复原状.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class LibpngFilter:
def __enter__(self):
self.pipe_in, pipe_out = os.pipe()
self.orig_fd = os.dup(2)
os.dup2(pipe_out, 2)
os.close(pipe_out)
self.stop = False

def reader():
f = os.fdopen(self.pipe_in)
for line in f:
if self.stop:
break
if line.startswith("libpng warning:"): # 屏蔽逻辑, 可以根据需要修改
break
sys.__stderr__.write(line)
sys.__stderr__.flush()
f.close()

self.thread = threading.Thread(target=reader, daemon=True)
self.thread.start()
return self

def __exit__(self, type, val, tb):
self.stop = True
os.dup2(self.orig_fd, 2)
os.close(self.orig_fd)
self.thread.join()

使用方法

1
2
3
with LibpngFilter():
...
# 处理 png 图片的代码

忽略 python 中 libpng 的 iCCP 警告
https://blog.xiyang6666.top/2025/06/01/忽略-python-中-libpng-的-iccp-警告/
作者
HanaTaka2137
发布于
2025年6月1日
许可协议