使用Python进行Windows桌面GUI自动化——睡眠vs紧密循环

5
我正在使用Python的PyAutoGUI库来自动化GUI。我要自动化的应用程序在我完成当前窗口的数据输入后会打开一个新窗口。Python自动化会处理一切(在当前窗口中进行数据输入和所需的单击操作)。
当在当前窗口中执行单击操作时,新窗口需要一些时间才能打开(可能需要2-5秒)。因此,我可以想到两个选项:
1. 使用`time.sleep(5)`休眠(缺点:可能浪费3秒钟的时间) 2. 在紧密循环中旋转,直到该窗口出现在屏幕上。 PyAutoGUI提供了一个`locateOnScreen`函数,可用于查找窗口是否实际出现在屏幕上。(然而,这是CPU密集型的,函数本身也是CPU密集型的,并且需要近2秒钟才能返回)
所以对我来说,[1]似乎是更好的选择。是否有其他技术我可能忽略了,比这两种方法更好?谢谢。

选项1是正确的选择。 - Ruslan
2
任何一种都不正确。您需要使用UI自动化WinEvents来获取创建/销毁的窗口通知。 - IInspectable
3个回答

5
仅适用于Windows的GUI自动化,pywinauto 功能更加全面(并且更符合Python风格)。它隐式地等待一些默认时间并允许显式等待(内部有一些CPU非密集型循环:一种0.1秒暂停和快速检查变化,然后再次等待)。
PyAutoGUI的 locateOnScreen 函数使用高级屏幕截图分析技术。这就是为什么它如此耗费CPU资源(但跨平台)。 pywinauto示例:
from pywinauto import Application

app = Application(backend="win32").start(u'your_app.exe')
app.MainWindow.menu_select(u'File->Open')

app.OpenDialog.Edit.set_edit_text(u'some path')
app.OpenDialog.Open.click()
app.OpenDialog.wait_not('visible', timeout=10)

new_main_window = app.window(title_re='^.* - The Software$')
new_main_window.wait('ready', timeout=15)

入门指南是学习pywinauto核心概念的好起点。


感谢您的回答,对于优秀的 pywinauto 库表示敬意和赞扬!但是我发现有些东西对我来说并没有按照预期工作。例如,当我在控制台中尝试 app.UntitledNotepad.Edit.TypeKeys("hello") 时,我只能在控制台上看到 "hello" 而不是在使用 pywinauto 打开的记事本上看到。我正在使用 Python 版本 3.4.3 和 pywinauto 版本 0.5.4。 - toddlermenot
嗯,看起来只有在我同时打开多个未保存的记事本时才会出现这种情况。 - toddlermenot
1
我们都需要感谢Mark制作了这样一个很酷的库。我们只是在尝试扩展它。顺便说一下,TypeKeys方法应该自动将焦点设置到目标窗口。或者您可以显式地执行app.UntitledNotepad.SetFocus() - Vasily Ryabov
1
太棒了!就是这样。由于某种原因,我必须明确地这样做。你们的工作真的很酷。很高兴看到一种通用脚本语言在桌面自动化方面不断发展,并与AutoHotkey和Autoit等软件竞争。 - toddlermenot
谢谢!这里有一个关于未来多后端接口的讨论。我们还需要一个适用于OS X的纯Python解决方案(目前没有好的想法)。任何帮助都将是有用的。 - Vasily Ryabov
显示剩余2条评论

2

我认为你可以使用pyautogui.getAllWindows()函数。该函数返回所有窗口及其句柄,因此您可以检查是否已添加新窗口。例如:

windows = pyautogui.getAllWindows()
windows_count = len(windows)
while True:
    current_windows = pyautogui.getAllWindows()
    if len(current_windows) != windows_count:
        break

此外,您可以使用所需窗口的句柄编号来激活该窗口并将其置于前景:
desired_window = pyautogui.Window(#enter window handle number)
desired_window.activate()

我认为更容易的另一种方法是pyautogui.getActiveWindowTitle()。此函数返回活动窗口的标题。或许您可以将其用于中断条件。

while True:
    title=pyautogui.getActiveWindowTitle()
    if title== "your desired window's title":
        break

0

我会选择第一种选项,但如果打开窗口所需的最小平均时间是2秒钟,那么我会睡2秒钟。2秒钟后,我会检查窗口是否出现,如果没有,那么我会再次睡2秒钟。这可能比睡5秒钟更节省时间。

但由于尝试检查窗口是CPU密集型和耗时的,我认为总体上等待5秒钟会更好。


谢谢,睡眠2秒的问题在于,如果没有绘制窗口,那么其余自动化代码(应该在新窗口上执行)也会执行,导致意外结果,例如其他后台窗口被最小化或关闭一些其他后台窗口。 - toddlermenot
我的回答不够清晰,而且我也没有考虑到定位窗口的函数会占用大量CPU资源。你是对的,等待5秒钟是更好的方法。 - masnun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接