使用mss截图遭遇ScreenShotError:gdi32.GetDIBits()失败如何解决?
gdi32.GetDIBits()失败的问题 我来帮你分析这个报错,我之前也遇到过类似的情况😉。首先看你的代码逻辑,循环里反复创建mss()实例是核心问题,再加上可能的截图区域合法性问题,共同导致了这个GDI调用失败的错误。
先把你的原代码和报错信息贴出来方便参考:
原代码
for i in range(1, 20000): cactus_box = {'left': 508, 'top': 382, 'width': 30, 'height': 33} sct = mss() sct_img = sct.grab(cactus_box)
报错信息
File "C:\Users\xxxx\AppData\Local\Programs\Python\Python36-32\lib\site-packages\mss\windows.py", line 203, in grab
raise ScreenShotError('gdi32.GetDIBits() failed.', locals())
mss.exception.ScreenShotError: ('gdi32.GetDIBits() failed.', {'bits': 0, 'height': 33, 'width': 30, 'gdi': <WinDLL 'gdi32', handle 75f00000 at 0x93dd5f0>, 'monitor': {'left': 508, 'top': 382, 'width': 30, 'height': 33}, 'self': <mss.windows.MSS object at 0x093DD810>})
具体解决方案
我整理了几个针对性的修复步骤:
复用mss实例,避免频繁创建:
mss实例初始化时会占用系统GDI资源,循环20000次反复创建会快速耗尽资源。把实例创建移到循环外面,用with语句还能自动管理资源释放,不用手动清理。检查截图区域是否在屏幕范围内:
如果你的cactus_box坐标超出了当前屏幕的宽高,GDI调用也会失败,所以先验证区域合法性很有必要。(可选)添加适当延迟:
20000次循环太密集,系统可能跟不上,加个小延迟(比如time.sleep(0.01))能降低资源压力,避免触发系统资源限制。
修改后的代码示例:
import mss import time # 可选,用于添加延迟 # 只初始化一次mss实例,with语句自动处理资源释放 with mss.mss() as sct: cactus_box = {'left': 508, 'top': 382, 'width': 30, 'height': 33} # 获取主显示器的分辨率信息 main_monitor = sct.monitors[1] # 检查截图区域是否合法 if (cactus_box['left'] + cactus_box['width'] > main_monitor['width'] or cactus_box['top'] + cactus_box['height'] > main_monitor['height']): print("错误:截图区域超出屏幕范围,请调整坐标!") else: for i in range(1, 20000): sct_img = sct.grab(cactus_box) # 这里可以添加你的截图处理逻辑,比如保存、分析等 # time.sleep(0.01) # 可选,根据需要添加延迟
这样修改后,应该能解决GDI资源耗尽的问题,同时避免无效的截图区域调用。
内容的提问来源于stack exchange,提问作者bav ko ten

