Bob's Blog

Web开发、测试框架、自动化平台、APP开发、机器学习等

返回上页首页

pywinauto中遇到ElementAmbiguousError错误的几种处理方式



pywinauto做为桌面端应用的自动化还是可行的,虽然不是那么好用,还需要用上pywin32的一些接口,但总归是一个可用的封装过的库。

最近用pywinauto和pywin32加上一些视觉技术在针对一个不是那么规范的windows老应用做自动化,做了一些额外的封装和处理。然后遇到了类似这样的报错:“pywinauto.findwindows.ElementAmbiguousError: There are 2 elements that match the criteria”. 看错误日志是找到了同样的元素,但实际上看到了窗口标识符类似导致的。发现和解决的过程中记录了一下这种报错的三种可能和解决方法。

1. 根据查找的条件确实有不止一个元素被找到。

这种情况需要指定唯一的需要的元素。比如app.child_window("class_name"="xxx", control_type="yyy") 在一个区域里找到了多个,此时加上found_index来限定哪一个。比如返回了3个,但需要第一个,则使用app.child_window("class_name"="xxx", control_type="yyy", found_index=0)。

但这种方式需要搞清楚需要的元素到底是第几个。

2. 和第一个一样,方式不同。

这个错误因为在指定的区域里找到了多个符合条件的。有时候是因为指定的区域过大,而child_window是类似于xpath里的//, 匹配了更大范围。此时可以将区域缩小。比如app.child_window.child_window, 多用几个child把区域限定得小一点,便能将同条件的元素分割开来。

3. 因为windows name是title_re导致的。

这个比较奇葩。有两个窗口,元素在A窗口上,不在B窗口上,但仍然报了There are 2 elements that match the criteria。

经过一步步的调试后发现,通过窗口名定位区域时使用了title_re,其实按理说两个不同的窗口名也不会在正则中相互匹配上。但是刚好遇到了窗口名踩到了正则通配符的坑。比如A窗口名是XXX|window,B窗口名是XXX|widget,两个名字是不一样的,但是|符号是正则中取左取右都行,于是匹配上了XXX,导致条件有2个窗口符合,也触发了这个报错。

这里的修改比较直接的可以修改pywinauto包里的findwindows.py,在274左右的位置开始加入两行,以处理|符号:

...
    elif title_re is not None:
        title_re = title_re.replace("|", "\|")   # added
        title_regex = re.compile(title_re)

        def _title_match(w):
            """Match a window title to the regexp"""
            t = w.rich_text
            if t is not None:
                t = t.replace("|", "\|")    # added
                return title_regex.match(t)
            return False
        elements = [elem for elem in elements if _title_match(elem)]
...

通过wheel unpack 包名,修改该文件,并修改dist-info目录里的METADATA等内容中的版本号,然后wheel pack 包名,重新打包。公司内部安装后就可以使用,自动化脚本可以不改。

下一篇:  MAUI加Blazor做一个跨平台的记账APP(二)新增账户页面
上一篇:  MAUI加Blazor做一个跨平台的记账APP(一)环境准备

共有0条评论

添加评论

暂无评论