使用 PyInstaller 创建的应用程序启动缓慢
Posted
技术标签:
【中文标题】使用 PyInstaller 创建的应用程序启动缓慢【英文标题】:App created with PyInstaller has a slow startup 【发布时间】:2012-03-17 05:11:01 【问题描述】:我有一个用 Python 编写并使用 PyInstaller“编译”的应用程序。它还使用 PyQt 作为 GUI 框架。
在主窗口加载并显示之前,运行此应用程序有大约 10 秒的延迟。据我所知,这不是由于我的代码运行缓慢。相反,我怀疑这是由于 Python 运行时初始化造成的。
问题是这个应用程序是使用自定义启动器/任务栏应用程序启动的。用户将单击按钮以启动应用程序,看到没有任何反应,然后单击另一个应用程序的其他位置。当我的应用程序显示它的窗口时,由于 SetForegroundWindow 的规则,它无法进入前台。
我可以访问 PyInstaller win32 加载程序、Python 代码甚至启动器代码的源代码。
我的问题是:
如何让这个应用程序启动更快?
如何衡量进程生命周期的前几秒所花费的时间?
在显示第一个窗口之前,普遍接受的缩短时间的技术是什么?
我想避免添加启动画面有两个原因 - 一,我认为它不会有帮助(开销是在 Python 代码运行之前),二,我只是不喜欢启动画面 :)
如果需要,我可能会编辑 PyInstaller 加载程序存根以创建一个窗口,但这是我不想采取的另一条路线。
【问题讨论】:
尝试关闭杀毒系统,可能对启动时间有很大影响。有关详细信息,请参见下文。 【参考方案1】:我怀疑您使用的是 pyinstaller 的“一个文件”模式——这种模式意味着它必须在应用程序启动之前将所有库解压到一个临时目录。在 Qt 的情况下,这些库非常大,需要几秒钟来解压缩。尝试使用“一个目录”模式,看看是否有帮助?
【讨论】:
【参考方案2】:告诉 PyInstaller 创建一个控制台模式的可执行文件。这为您提供了一个可用于调试的工作控制台。
在主脚本的顶部,甚至在第一次导入运行之前,添加打印“Python 代码开始”。然后从命令行运行打包的可执行文件。通过这种方式,您可以清楚地了解时间是花在 PyInstaller 的引导加载程序中还是在您的应用程序中。
PyInstaller 的引导加载程序在单目录模式下通常非常快,但在单文件模式下可能会慢得多,因为它将所有内容解包到一个临时目录中。在 Windows 上,I/O 非常慢,然后您的防病毒软件会想要仔细检查所有这些 DLL 文件。
PyQt 本身不是问题。 PyQt 由 SIP 生成,SIP 生成非常快的惰性绑定;导入整个 PyQt 比任何其他 GUI 库都快,因为它基本上什么都不做:所有与类/函数的绑定都是在您访问它们时(如果!)动态创建的,也节省了大量内存。
如果您的应用程序启动速度很慢,那么在没有 PyInstaller 的情况下也是如此。在这种情况下,您唯一的解决方案是启动屏幕(仅导入 PyQt,创建 QApplication,创建显示启动屏幕,然后导入程序的其余部分并运行它),或者重新编写代码。没有细节我帮不了你。
【讨论】:
你说得对,我创建了一个更简单的应用程序,实际上启动时间几乎是即时的。我正在使用 onedir 模式。我相信问题是我的几个进口。我还有很多事情要做。 哇,感谢您提供有关防病毒的提示。一旦我禁用了我的 AV,我的 exe 就会加速。【参考方案3】:我同意上述答案。使用 onefile 模式时,我的 Qt python 程序需要大约 5 秒才能在一台不错的 PC 上启动。在我更改为 --onedir 后,启动只需要大约一秒钟;在用户双击 exe 文件后几乎立即。但缺点是那个目录下的文件很多,不太整齐。
【讨论】:
【参考方案4】:对于我的应用程序,启动时间过长几乎完全是由防病毒系统引起的。关闭它可以将我的启动时间从 3 分钟缩短到不到 10 秒!
为了让这些测量结果更直观:我的应用程序捆绑了额外的数据文件(大约 150 个文件,有效负载为 250MB),此外还携带 Qt 和 numpy(这可能取决于英特尔 MKL,仅此一项就增加了 200MB 到捆绑!)依赖项。测试系统使用固态驱动器运行甚至没有多大帮助...
总结:如果你的应用程序很大,依赖很多,启动时间可能会受到杀毒系统的强烈影响!
【讨论】:
【参考方案5】:如果有人仍然有这个问题,我通过在本地而不是在任何共享驱动器上运行 exe 来解决我的问题。这使启动时间从一分钟多到了不到 10 秒。
【讨论】:
【参考方案6】:我已经使用 py2exe 和 cx_Freeze “编译”了一些 wxPython 应用程序,它们的启动时间都不超过 4 秒。
您确定这不是您的代码吗? 可能是某个网络或某个 I/O 资源调用持有您的应用? 您尝试过其他机器吗?即使是最快的硬件有时也会因为错误的软件配置、应用或操作系统而变慢,试试吧。 尝试使用 timeit 模块对其进行计时。我没用过pyQT,但是wxPython启动速度还可以,第一次初始化后关闭再打开,比第一次还快。
【讨论】:
在执行任何代码之前,将 .exe 及其所有依赖项和库解压到临时 (_MEIxxxx
) 文件夹中比较慢。即使print("Hello world!")
也需要 10 秒才能加载。【参考方案7】:
我通过在防病毒监控软件 (F-Secure
) 中添加异常解决了这个问题。它消除了运行前几分钟的等待。
【讨论】:
以上是关于使用 PyInstaller 创建的应用程序启动缓慢的主要内容,如果未能解决你的问题,请参考以下文章
使用 --onefile 和 --noconsole 使用 PyInstaller 编译的 PyQt5 应用程序,但 exe 无法启动
Python为PyInstaller打包后的程序搞一个小小的启动器
Python为PyInstaller打包后的程序搞一个小小的启动器
Python为PyInstaller打包后的程序搞一个小小的启动器
使用 PyInstaller 编译得到 pyodbc 后如何在启动时修复错误?
使用 Fbs/PyInstaller 冻结我的应用程序导致在另一台电脑上启动时无法执行 pyi_rth_qt5plugins