一.简介
1.在上一篇中在start()后,加入适当的等待时间(如time.sleep()),让应用程序有足够的时间初始化窗口和UI元素1.1.之前在做web和app的ui自动化过程中,常用到等待机制,那PC端自动化有这个方法吗?1.2.答案是肯定的,python这么强大,肯定是有方法的2.PC端自动化是如何等待的2.1.应用程序行为通常不稳定,脚本需要等待,直到出现新窗口或关闭/隐藏现有窗口2.2.pywinauto可以隐式地(默认超时)灵活地等待对话框初始化,或者明确地使用专用方法/函数来帮助您使代码更容易和更可靠二.等待机制
1.分为三个大类(仅是自己的观点):窗口/元素等待、应用程序等待和全局等待时间Timings2.窗口/元素等待2.1.Pywinauto是用于自动化Windows GUI应用程序的模块,提供了两种等待函数:wait()和wait_not()2.1.1.wait():等待窗口达到指定状态2.1.2.wait_not():等待窗口不处于某种状态2.2.wait()2.2.1.wait()函数用于等待指定窗口达到指定状态,例如“最大化”或“最小化”状态2.2.2.可以通过设置超时时间和重试间隔来控制等待的时间和频率2.2.3.wait()的源码defwait(self,wait_for,timeout=None,retry_interval=None):""" Wait for the window to be in a particular state/states. :param wait_for: The state to wait for the window to be in. It can be any of the following states, also you may combine the states by space key. * 'exists' means that the window is a valid handle * 'visible' means that the window is not hidden * 'enabled' means that the window is not disabled * 'ready' means that the window is visible and enabled * 'active' means that the window is active :param timeout: Raise an :func:`pywinauto.timings.TimeoutError` if the window is not in the appropriate state after this number of seconds. Default: :py:attr:`pywinauto.timings.Timings.window_find_timeout`. :param retry_interval: How long to sleep between each retry. Default: :py:attr:`pywinauto.timings.Timings.window_find_retry`. An example to wait until the dialog exists, is ready, enabled and visible: :: self.Dlg.wait("exists enabled visible ready") .. seealso:: :func:`WindowSpecification.wait_not()` :func:`pywinauto.timings.TimeoutError` """check_method_names,timeout,retry_interval=self.__parse_wait_args(wait_for,timeout,retry_interval)wait_until(timeout,retry_interval,lambda:self.__check_all_conditions(check_method_names,retry_interval))# Return the wrapped controlreturnself.wrapper_object()2.2.4.参数说明2.2.4.1.wait_for可选参数2.2.4.1.1.‘exists’:表示窗口存在,是一个有效的句柄2.2.4.1.2.‘visible’:表示窗口可见(不隐藏)2.2.4.1.3.‘enabled’:表示窗口未被禁用2.2.4.1.4.‘ready’:表示窗口可见且已启用2.2.4.1.5.‘active’:表示窗口处于活动状态2.2.4.2.timeout:表示超时时间2.2.4.3.retry_interval:表示重试间隔2.3.wait_not()2.3.1.其实和上面都是一样的,一种等待处于某种状态,一种等待不处于某种状态2.3.2.wait_not()函数则用于等待指定窗口不处于某种状态,例如“关闭”状态2.3.3.它的使用方式与wait()函数类似,但参数和返回值有所不同2.3.4.wait_not()的源码defwait_not(self,wait_for_not,timeout=None,retry_interval=None):""" Wait for the window to not be in a particular state/states. :param wait_for_not: The state to wait for the window to not be in. It can be any of the following states, also you may combine the states by space key. * 'exists' means that the window is a valid handle * 'visible' means that the window is not hidden * 'enabled' means that the window is not disabled * 'ready' means that the window is visible and enabled * 'active' means that the window is active :param timeout: Raise an :func:`pywinauto.timings.TimeoutError` if the window is sill in the state after this number of seconds. Default: :py:attr:`pywinauto.timings.Timings.window_find_timeout`. :param retry_interval: How long to sleep between each retry. Default: :py:attr:`pywinauto.timings.Timings.window_find_retry`. An example to wait until the dialog is not ready, enabled or visible: :: self.Dlg.wait_not("enabled visible ready") .. seealso:: :func:`WindowSpecification.wait()` :func:`pywinauto.timings.TimeoutError` """check_method_names,timeout,retry_interval=\ self.__parse_wait_args(wait_for_not,timeout,retry_interval)wait_until(timeout,retry_interval,lambda:notself.__check_all_conditions(check_method_names,retry_interval))# None return value, since we are waiting for a `negative` state of the control.# Expect that you will have nothing to do with the window closed, disabled, etc.2.3.5.参数说明2.3.5.1.wait_not可选参数2.3.5.1.1.‘exists’:表示窗口存在,是一个有效的句柄2.3.5.1.2.‘visible’:表示窗口可见(不隐藏)2.3.5.1.3.‘enabled’:表示窗口未被禁用2.3.5.1.4.‘ready’:表示窗口可见且已启用2.3.5.1.5.‘active’:表示窗口处于活动状态2.3.5.2.timeout:表示超时时间2.3.5.3.retry_interval:表示重试间隔三.应用程序等待
1.应用程序等待只是针对应用程序的2.注意:此方法仅适用于整个应用程序进程,不适用于窗口/元素3.CPU使用率3.1.wait_cpu_usage_lower()3.1.1.wait_cpu_usage_lower(),等待该进程的cup的使用率低于某个阀值3.1.2.wait_cpu_usage_lower()的源码defwait_cpu_usage_lower(self,threshold=2.5,timeout=None,usage_interval=None):"""Wait until process CPU usage percentage is less than the specified threshold"""ifusage_intervalisNone:usage_interval=Timings.cpu_usage_intervaliftimeoutisNone:timeout=Timings.cpu_usage_wait_timeout start_time=timings.timestamp()whileself.cpu_usage(usage_interval)>threshold:iftimings.timestamp()-start_time>timeout:raiseRuntimeError('Waiting CPU load <= {}% timed out!'.format(threshold))returnself3.1.3.参数说明3.1.3.1.threshold:表示该进程cup占用率3.1.3.2.timeout:表示超时时间3.1.3.3.retry_interval:表示重试间隔4.进程4.1.wait_for_process_exit()4.1.1.wait_for_process_exit(),等待进程退出,直到超时4.1.2.wait_for_process_exit()的源码defwait_for_process_exit(self,timeout=None,retry_interval=None):""" Waits for process to exit until timeout reaches Raises TimeoutError exception if timeout was reached """iftimeoutisNone:timeout=Timings.app_exit_timeoutifretry_intervalisNone:retry_interval=Timings.app_exit_retry wait_until(timeout,retry_interval,self.is_process_running,value=False)4.1.3.参数说明4.1.3.1.timeout:表示超时时间4.1.3.2.retry_interval:表示重试间隔四.timings
1.pywinauto 查找窗口和控件时会有超时时间与轮询机制,可以通过timings 模块设置全局等待时间2.timings模块2.1.timings 模块有三个模式可以设置2.1.1.timings.Timings.fast():快速模式2.1.2.timings.Timings.defaults():默认模式2.1.3.timings.Timings.slow():慢速模式2.2.以下是可以调整的各个时序设置window_find_timeout(default5)window_find_retry(default.09)app_start_timeout(default10)app_start_retry(default.90)app_connect_timeout(default5.)app_connect_retry(default.1)cpu_usage_interval(default.5)cpu_usage_wait_timeout(default20)exists_timeout(default.5)exists_retry(default.3)after_click_wait(default.09)after_clickinput_wait(default.09)after_menu_wait(default.1)after_sendkeys_key_wait(default.01)after_button_click_wait(default0)before_closeclick_wait(default.1)closeclick_retry(default.05)closeclick_dialog_close_wait(default2)after_closeclick_wait(default.2)after_windowclose_timeout(default2)after_windowclose_retry(default.5)after_setfocus_wait(default.06)setfocus_timeout(default2)setfocus_retry(default.1)after_setcursorpos_wait(default.01)sendmessagetimeout_timeout(default.01)after_tabselect_wait(default.05)after_listviewselect_wait(default.01)after_listviewcheck_wait default(.001)listviewitemcontrol_timeout default(1.5)after_treeviewselect_wait default(.1)after_toobarpressbutton_wait default(.01)after_updownchange_wait default(.1)after_movewindow_wait default(0)after_buttoncheck_wait default(0)after_comboboxselect_wait default(.001)after_listboxselect_wait default(0)after_listboxfocuschange_wait default(0)after_editsetedittext_wait default(0)after_editselect_wait default(.02)drag_n_drop_move_mouse_wait default(.1)before_drag_wait default(.2)before_drop_wait default(.1)after_drag_n_drop_wait default(.1)scroll_step_wait default(.1)3.设置模式3.1.想让操作更快一点,可以设置快速模式3.2.想让操作更慢一点,可以设置慢速模式3.3.设置方法还是比较简单的,导入模块后,一行代码即可搞定3.4.快速模式:快速模式的设置方式frompywinauto.applicationimportApplicationfrom pywinauto.timingsimportTimings Timings.fast()3.5.慢速模式:慢速模式的设置方式frompywinauto.applicationimportApplicationfrom pywinauto.timingsimportTimings Timings.slow()五.趁热打铁
1.测试场景1.1.测试场景:启动电脑的notepadd++编辑器这款软件,然后输入内容:x京x哥,最后点击notepadd++编辑器左上角的【文件(F)->另存为(A)...】,然后等待另存为的窗口出现即可!2.代码设计frompywinautoimportApplication# 通过窗口打开app=Application('uia').start("D:/software/Notepad/Notepad++/notepad++.exe")app=Application('uia').connect(class_name="Notepad++")# win = app['窗口的标题']win=app['新文件1 - Notepad++']#输入内容:北京-宏哥win.type_keys("北京-宏哥")win.child_window(title="应用程序",auto_id="MenuBar",control_type="MenuBar")# 文件-另存为win.menu_select('文件(F) -> 另存为(A)...')# 等待另存为窗口出现win.child_window(title="另存为",control_type="Window").wait('ready',timeout=5)3.运行代码,右键Run'Test',就可以看到控制台输出4.运行代码后电脑端的动作(启动记事本)六.总结
1.基础窗口状态等待方法1.1.wait()方法支持等待窗口达到特定状态1.1.1.'exists':窗口句柄有效1.1.2.'visible':窗口未隐藏1.1.3.'enabled':窗口未被禁用1.1.4.'ready':窗口可见且已启用1.1.5.'active':窗口处于活动状态1.2.参数说明1.2.1.timeout:超时时间(默认由全局配置决定)1.2.2.retry_interval:重试间隔(默认由全局配置决定)2.高级场景等待方法2.1.wait_cpu_usage_lower():适用于多线程应用中延迟初始化的场景,通过监控进程的CPU使用率判断任务是否完成(如后台计算未结束前保持等待)2.2.wait_until_passes():持续执行指定操作直至成功或超时,特别适用于动态加载的控件或异步操作后的状态检测3.全局等待时间配置3.1.通过 timings 模块设置默认超时和轮询间隔3.1.1.Timings.Defaults.timeout:全局超时时间(默认30秒)3.1.2.Timings.Defaults.retry_interval:全局重试间隔(默认0.5秒)4.使用建议4.1.优先使用内置等待机制(如 wait()和 wait_until_passes()),避免依赖 time.sleep(),以提高代码稳定性和执行效率4.2.对于复杂界面,结合 print_control_identifiers()输出控件信息以辅助定位目标元素5.注:以上方法需根据具体场景选择,合理设置超时参数可避免因界面响应延迟导致的自动化失败