在使用selenium库做WEB自动化测试时,当测试用例执行过程发生异常时,按照需求时需要将当时浏览器窗口保存截图,最开始使用了webdriver的内置的方法:
wb.get_screenshot_as_file(file_path)
但是找个方法截图的只是浏览器内容区,标题栏及打开的浏览器无法呈现出来,因此测试人员不满意这种异常出现时的现场截图。
经过查阅资料,选择了pyautogui这个三方模块。使用了该库的截图功能进行系统屏幕截取,这个方法本地验证也没问题,也就很快上线使用了。
screen = pyautogui.screenshot() screen.save('test.png')
由于上面的代码我使用了try来捕获异常,发生异常时,使用wb.get_screenshot_as_file(file_path)来进行兜底。
问题出现:
上线后问题很快就出现了,部分主机截图还是只显示内容区,不是整个浏览器屏幕。也就是说在使用pyautogui进行截图时发生异常了。
通过mstsc远程到云主机重新跑用例进行问题分析定位,无论如何不能复现,而且截图正常,没有任何异常输出。下面是我的截图代码,我反反复复验证了无数次,后使用PIL库,甚至使用了模拟按下键盘printScreen按键,读取内存的方式保存图片。都无法有效将这个问题解决,查了很多网上的分析,有说是安全问题,有说是刚开始用的好好的,运行几分钟之后就不行了。
问题分析:
偶然间程序在后台运行,我桌面锁屏了,后来打开控制台,异常出现了。
try:
# 模拟按下 PrtScn 键
pyautogui.keyDown('printscreen')
pyautogui.keyUp('printscreen')
# 获取剪贴板中的图像数据
screenshot = ImageGrab.grabclipboard()
# 保存截图为文件
if screenshot is not None:
screenshot.save(file_path)
else:
print("Failed to capture screenshot")
except Exception as e:
print('使用printscreen截屏失败')
print(e)
try:
# 优先使用PIL截取整个屏幕
screenshot = ImageGrab.grab()
screenshot.save(file_path)
except Exception as e:
print('使用PIL截屏出现异常')
print(e)
try:
screenshot = pyautogui.screenshot()
screenshot.save(file_path)
except Exception as e:
print('使用pyautogui截屏出现异常,只截取浏览器内容区')
print(e)
if self.wb:
self.wb.get_screenshot_as_file(file_path)
else:
print('在尝试截屏时出现异常')
Traceback (most recent call last):
File "D:/spug/waterRPA/drinkWater.py", line 18, in <module>
screen = pyautogui.screenshot()
File "D:\spug\waterRPA\venv\lib\site-packages\pyscreeze\__init__.py", line 538, in _screenshot_win32
im = ImageGrab.grab(all_screens=allScreens)
File "D:\spug\waterRPA\venv\lib\site-packages\PIL\ImageGrab.py", line 47, in grab
offset, size, data = Image.core.grabscreen_win32(
OSError: screen grab failed
到这里,我有充分理由怀疑,是云上主机锁屏导致,由于先前知道云上主机是自动登录的,并且会禁用了锁屏,因此没有往这个方面去怀疑,后来,通过查阅资料发现,通过mstsc远程后,再断开,通过VNC查看桌面就处于锁屏状态,相当于电脑的显示器看到的就是锁屏状态。导致上面的报错OSError: screen grab failed。
解决问题:
后面在执行任务之前,通过代码判断系统是否处于锁屏状态,则通过命令让系统强制重启,这样系统重启后,有自动登录和应用自动重启,就可以顺利截屏了。
总结:
用户通过mstsc远程连接到云主机并断开后导致系统锁屏,系统锁屏状态下调用
screen = pyautogui.screenshot()
screen.save('test.png')会抛异常。
建议:
1、如果主机比较多,通过代码判断是否锁屏了,如果锁屏让系统自动重启自动登录。
2、如果主机少,可以直接通过VNC连接桌面解锁登录(缺点是其他人用mstsc连接并断开后,仍会导致系统锁屏)。