
一.简介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,timeoutNone,retry_intervalNone): 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_intervalself.__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,timeoutNone,retry_intervalNone): 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,threshold2.5,timeoutNone,usage_intervalNone):Wait until process CPU usage percentage is less than the specified thresholdifusage_intervalisNone:usage_intervalTimings.cpu_usage_intervaliftimeoutisNone:timeoutTimings.cpu_usage_wait_timeout start_timetimings.timestamp()whileself.cpu_usage(usage_interval)threshold:iftimings.timestamp()-start_timetimeout: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,timeoutNone,retry_intervalNone): Waits for process to exit until timeout reaches Raises TimeoutError exception if timeout was reached iftimeoutisNone:timeoutTimings.app_exit_timeoutifretry_intervalisNone:retry_intervalTimings.app_exit_retry wait_until(timeout,retry_interval,self.is_process_running,valueFalse)4.1.3.参数说明4.1.3.1.timeout表示超时时间4.1.3.2.retry_interval表示重试间隔四.timings1.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# 通过窗口打开appApplication(uia).start(D:/software/Notepad/Notepad/notepad.exe)appApplication(uia).connect(class_nameNotepad)# win app[窗口的标题]winapp[新文件1 - Notepad]#输入内容北京-宏哥win.type_keys(北京-宏哥)win.child_window(title应用程序,auto_idMenuBar,control_typeMenuBar)# 文件-另存为win.menu_select(文件(F) - 另存为(A)...)# 等待另存为窗口出现win.child_window(title另存为,control_typeWindow).wait(ready,timeout5)3.运行代码右键RunTest就可以看到控制台输出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.注以上方法需根据具体场景选择合理设置超时参数可避免因界面响应延迟导致的自动化失败