前言
上一篇文章地址:
pywinauto:Windows桌面应用自动化测试(九)-优快云博客
下一篇文章地址:
暂无
一、查找属性小结
通过查看源码与官方文档,我们发现方法window、child_window、children的参数都依赖于非常低级的 API,即find_elements方法
,因此,我们只要将find_elements的参数与inspect查找到的属性对应起来,就可以根据inspect查找到的属性快速定位元素,如下表所示:
find_elements 参数 | inspect 获取的属性 | 说明 |
---|---|---|
class_name | ClassName | 匹配控件的类名,使用类名精确匹配控件类型。如果 ClassName 是空值,表示没有匹配到类名。 |
class_name_re | ClassName | 使用正则表达式匹配控件的类名。 |
parent | Ancestors , Parent | 控件的父控件,通过 Parent 或 Ancestors 属性来指定父窗口或控件。 |
process | ProcessId | 控件所属的进程 ID,通过 ProcessId 属性匹配。 |
title | Name , LegacyIAccessible.Name | 控件或窗口的标题或文本内容,精确匹配。 |
title_re | Name , LegacyIAccessible.Name | 使用正则表达式匹配控件的标题或文本内容。 |
top_level_only | 是否为顶层窗口 | 是否只查找顶层控件,True 为只查找顶层控件,False 包括嵌套子控件。 |
visible_only | IsOffscreen | 控件的可见性,True 表示只查找可见控件 (IsOffscreen=False )。 |
enabled_only | IsEnabled | 控件的启用状态,True 表示只查找启用的控件。 |
best_match | Name , LegacyIAccessible.Name | 查找名称与指定字符串相似的控件,允许模糊匹配。 |
handle | hwnd | 控件的唯一句柄,通过 hwnd 来精确匹配控件。 |
ctrl_index | GridItem.Row , GridItem.Column | 指定控件在父控件中的索引或网格位置。 |
found_index | 索引 (在界面上查找的顺序) | 在查找到的控件集合中,通过索引获取特定控件。 |
predicate_func | 自定义属性 | 自定义的函数,用于自定义过滤控件。 |
active_only | IsActive (未在此属性中体现) | 只查找当前活动的控件。 |
control_id | ControlId , AutomationId | 控件的唯一 ID,通过 ControlId 或 AutomationId 来唯一匹配控件。 |
control_type | ControlType , LocalizedControlType | 控件的类型,如 Button 、Edit 等。 |
auto_id | AutomationId | 控件的自动化 ID,通过 AutomationId 唯一匹配控件。 |
framework_id | FrameworkId | 控件所属的框架 ID,如 Win32 、Chrome 等。 |
backend | 与自动化后端相关 | 指定使用的自动化后端,如 "win32" 或 "uia" 。 |
depth | 控件层次深度 | 控件的层次深度,用于控制查找的递归层级。 |
在使用 Pywinauto 进行元素定位时,不同属性有不同的简易程度和精确度。以下是对常见属性的优先级排序,基于简易程度、精确度和常见用例进行考虑:
属性 | 优先级 | 简易程度 | 精确度 | 备注 |
---|---|---|---|---|
best_match | 1 | 高 | 高 | 基于控件的最佳匹配,最常用,适合简单界面中的大部分场景,易于理解和使用。 |
handle | 2 | 中 | 最高 | 通过唯一的窗口句柄定位,适合需要唯一标识控件的情况,精确度最高,但不易获取,需要更多的准备工作。 |
control_id | 3 | 中 | 高 | 通过控件的唯一 ID 定位,常用于 Win32 应用中,适合唯一标识的控件,精确度很高,但前提是知道控件的 ID。 |
class_name | 4 | 高 | 中高 | 通过控件类名定位,简易程度高,适合同类型控件较多的情况,如所有按钮都有相同类名。精确度取决于控件的唯一性,适合大范围初步筛选。 |
title /name | 5 | 高 | 高 | 使用控件的文本或标题进行定位,适合大部分窗口标题、按钮等带有文本的控件。对文本敏感,适合标识唯一控件。 |
auto_id | 6 | 低 | 高 | 使用 UIAutomation 自动生成的 ID,适合现代应用程序,但不是所有应用都支持,支持则精确度较高。 |
class_name_re | 7 | 中 | 中高 | 通过正则表达式匹配控件类名,灵活性强,适合需要匹配多个类名的场景。精确度和简易度依赖于正则表达式的复杂程度。 |
title_re | 8 | 中 | 中高 | 通过正则表达式匹配控件的标题或文本,适合标题变化不大但模式一致的场景。适合动态内容,简易度取决于正则表达式。 |
visible_only | 9 | 高 | 中 | 仅搜索可见的控件,通常用于避免查找隐藏控件,简易程度高,但精确度不高,主要用于初步筛选。 |
enabled_only | 10 | 高 | 中 | 仅搜索启用的控件,类似 visible_only ,但用于筛选可操作的控件。通常与其他定位方法结合使用。 |
depth | 11 | 中低 | 中高 | 限定搜索的控件深度,适用于控件层次复杂的 UI 界面,但需要明确层级结构,简易度低,适合高效筛选。 |
parent | 12 | 低 | 中 | 限定控件的父级控件,适合在嵌套复杂的界面中定位元素。简易度低,使用时需要清楚控件的层次结构,适合在多层结构中准确定位。 |
process | 13 | 低 | 中 | 限定属于特定进程的控件,适用于进程内多个窗口的定位,简易度低,通常用于精细化筛选。 |
predicate_func | 14 | 低 | 高 | 用户自定义的筛选函数,灵活性和精确度高,但实现难度大,适合高级用户进行复杂控件筛选。 |
二、实战常用方法
1、细聊child_window机制
为什么pywinauto使用.child_window(title="666")找元素,title无论怎么赋值都不会报错?
(1)child_window()
的懒加载机制:
pywinauto
的 .child_window()
方法使用的是一种“懒加载”机制,意味着当你调用 .child_window()
方法时,它并不会马上执行查找,而是创建了一个 查找器对象。这个对象仅保存了搜索条件,并不会立即验证这些条件是否能找到目标控件。
只有在后续调用方法(如 .click()
、.type_keys()
或 .wait()
)时,pywinauto
才真正执行控件查找。如果找不到目标控件,才会抛出错误。
(2)宽松的条件匹配:
.child_window()
允许传入多个条件(如 title
, control_type
, class_name
),但这些条件并不要求全都匹配。比如你只传入了 title="666"
,即使界面上没有任何控件满足这个条件,它依然不会报错,除非你后续调用了具体操作方法。这种宽松的机制允许你进行更加复杂的控件查找。
(3)报错时机:
如果控件找不到,会在尝试对该控件进行交互(如 .click()
、.set_text()
、.wait()
)时抛出 ElementNotFoundError
或者 AttributeError
,而不是在定义 .child_window()
时。
2、wait()的使用方式
官方文档:
wait(wait_for, timeout=None, retry_interval=None)
Wait for the window to be in a particular state/states.
Parameters:
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
timeout – Raise an pywinauto.timings.TimeoutError() if the window is not in the appropriate state after this number of seconds. Default: pywinauto.timings.Timings.window_find_timeout.
retry_interval – How long to sleep between each retry. Default: 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")
解释:
wait(wait_for, timeout=None, retry_interval=None)
是 pywinauto
中一个非常实用的方法,用于等待窗口达到特定的状态。它允许你在对窗口进行交互之前,确保窗口已经处于所需的状态,如存在、可见、启用等。这可以避免由于窗口尚未准备好而导致的错误。
(1)wait_for
:
可以通过空格分隔符组合多个状态。例如:"exists enabled visible ready"
。支持以下状态:
exists
:窗口句柄已存在,表示窗口是一个有效的句柄。
visible
:窗口可见,意味着窗口未被隐藏。
enabled
:窗口已启用,意味着窗口未被禁用。
ready
:窗口既可见又启用,通常在与控件交互之前,确保窗口处于可用状态。
active
:窗口是当前活动的窗口,焦点在该窗口上。
(2)timeout
:
指定等待窗口达到目标状态的最大时长(以秒为单位)。如果在规定时间内窗口未达到指定状态,则抛出 pywinauto.timings.TimeoutError()
错误。默认值为pywinauto.timings.Timings.window_find_timeout
,通常是 5 秒。(3)retry_interval
:
指定在每次重试查找窗口状态之间的间隔时间(以秒为单位)。默认值为 pywinauto.timings.Timings.window_find_retry
,通常是 0.1 秒。