在 macOS [python、PySimpleGUI、Tkinter、macOS 中通过 tkinter 刷新(更新)非常慢 window

Very slow window refresh (update) via tkinter in macOS [python, PySimpleGUI, Tkinter, macOS]

我们的应用程序(基于Python,cythonised 和打包用于未安装 Python 的计算机)具有基于 PySimpleGUI / Tkinter 端口的 GUI。

在 macOS 中,我们有时会遇到启动极其缓慢的情况。在我的 Mac 上,从应用程序启动到主 window 完全呈现并准备好使用它只需要大约 2-3 秒。但是在我一些同事的 Macs 上,有时需要 45s 甚至几分钟。我们在较早版本的应用程序中遇到了这个问题,但在 5 月份通过添加启动 window 解决了这个问题,如 中所述。新版本(= 启动 window)总是在不同地方的所有可用计算机上快速启动(2-3 秒)数周,但随后(虽然我们没有更改应用程序中的任何内容),速度缓慢 -启动问题再次出现 - 仅在某些 Mac 上出现,甚至取决于位置:在我同事的计算机上,该应用程序始终以最大启动。上班时间 3 秒,在家时 45 秒以上。

我们的应用程序有 Mac、Windows 和 Linux 版本。只有 Mac 版本有这个问题(到目前为止在 Win 下从未观察到,Linux 并且在 Mac 上的 Win/Linux 模拟器中也从未观察到),仅在某些计算机上与某些结合使用位置。在工作中,我们团队使用的所有电脑都很快,但我们 一些 客人的电脑速度很慢;对于我的同事,在(她)家慢;在(我的)家里,在我的电脑上速度很快,但在另一台电脑上速度很慢。这让我很困惑!

我在代码中添加了很多日志记录,以便能够查看代码的哪些部分花费了很多时间。只有一次网络交互(许可证验证),而且看起来并不慢:整个功能(建立连接、检索数据、处理数据、关闭连接)即使启动时间超过 45 秒也不会超过 2 秒.我们能看到的所有延迟都与 main-window refresh:

有关
logging.info('.created background window', session_log=True)
main_window.refresh()
logging.info('.refreshed main window', session_log=True)

只是这个 refresh() 在那些缓慢的启动上需要 3-10 秒甚至更多的时间。它是 PySimpleGUI 的一个函数,定义如下:

    def refresh(self):
        if self.TKrootDestroyed:
            return self
        try:
            rc = self.TKroot.update()
        except:
            pass
        return self

在主要 window 完全渲染后,相同的功能被多次使用,但它们再也不会变慢了;它总是处于应用程序的启动阶段。

所以,似乎是 Tkinter 的 update() 花了这么长时间。但为什么只在某些 Mac 上,并且(在同一个 Mac 上)为什么只在某些地方?

您在 GUI 中遇到过这种情况吗?你有什么想法如何处理它吗?

如有任何提示,我将不胜感激。

我建议用 .updateidletasks() 替换对 .update() 的调用。 update 不仅会导致 window 刷新,而且它必须处理所有类型的所有未决事件,并且不会 return 直到所有事件都处理完毕。如果在处理事件时再次调用此代码,您最终会在事件循环中嵌套事件循环。

updateidletasks 只处理空闲队列中的事件,主要是 after_idle 的屏幕更新和作业队列,大大减少了嵌套事件循环的可能性。