PyInstaller创建的应用程序启动缓慢

94

我有一个用Python编写并使用PyInstaller“编译”的应用程序,并使用PyQt作为GUI框架。

在主窗口加载和显示之前,运行此应用程序会有大约10秒的延迟。据我所知,这不是由于我的代码缓慢,而是由于Python运行时初始化造成的。

问题在于,此应用程序使用自定义启动器/任务栏应用程序启动。用户将点击按钮以启动应用程序,看起来似乎没有发生任何事情,然后在其他应用程序上单击。当我的应用程序显示其窗口时,由于SetForegroundWindow的规则,它无法到达前台。

我可以访问PyInstaller win32 loader、Python代码甚至是启动器代码的源代码。

我的问题是:

  • 如何使此应用程序更快地启动?

  • 如何测量进程生命周期的前几秒钟花费的时间?

  • 通常接受的减少时间直到第一个窗口显示的技术是什么?

我希望避免添加闪屏,原因有两个:首先,我认为它不会有所帮助(开销出现在Python代码运行之前),其次,我就是不喜欢闪屏:)

如果必要,我可能可以编辑PyInstaller加载程序存根以创建窗口,但这是另一条路线,我不太想走。


1
尝试关闭防病毒系统,这可能会对启动时间产生很大影响。有关更多详细信息,请参见下文。 - normanius
8个回答

88

我猜测你正在使用pyinstaller的“一个文件”模式——这种模式意味着在应用程序启动之前必须将所有库解压缩到临时目录中。就Qt而言,这些库非常大,需要几秒钟的时间来解压缩。尝试使用“一个目录”模式,看看是否有所帮助?


52

告诉PyInstaller创建控制台模式的可执行文件。这样你就可以使用工作中的控制台进行调试。

在你的主脚本顶部,在第一个import之前,添加一个打印语句“Python Code starting”。然后从命令行运行打包后的可执行文件。这样你就可以清楚地了解时间是花在PyInstaller的引导程序还是在你的应用程序中。

在一个目录模式下,PyInstaller的引导程序通常非常快,但在一个文件模式下可能会慢得多,因为它将所有内容解压到一个临时目录中。在Windows上,I/O非常缓慢,然后你有一些杀毒软件会想要对所有这些DLL文件进行双重检查。

PyQt本身不是问题。PyQt由SIP生成,它生成非常快速的延迟绑定;导入整个PyQt比任何其他GUI库都要快,因为它基本上什么都不做:当(如果!)你访问它们时,所有类/函数的绑定都是动态创建的,也节省了大量内存。

如果你的应用程序启动缓慢,那么即使没有PyInstaller,这也是正确的。在这种情况下,你唯一的解决方案就是要么使用启动画面(仅导入PyQt,创建QApplication,创建显示启动画面,然后导入其余的程序并运行它),要么重新设计你的代码。我没有详细信息无法提供更多帮助。


3
你是对的,我创建了一个更简单的应用,启动时间确实几乎瞬间完成了。我正在使用onedir模式。我相信问题在于我的多个导入。我还需要做更多的追踪工作。 - EB.
2
哇,谢谢你提供的关于杀毒软件的提示。一旦我禁用了我的杀毒软件,我的可执行文件就加快了速度。 - iridescent

16

我同意上面的回答。当我在一个文件模式下使用我的Qt python程序时,在一台不错的电脑上需要约5秒钟启动。但是当我改用--onedir模式后,只需要大约一秒钟就能启动;用户双击exe文件后几乎立即启动。但缺点是该目录中有很多文件,不太整洁。


4

如果仍然存在这个问题,我解决了我的问题:在本地运行exe文件而不是共享驱动器上运行。 这将启动时间从一分钟以上缩短到不到10秒钟。


4

对于我的应用程序,长时间的启动几乎完全是由于杀毒系统引起的。将其关闭后,在我的情况下,启动时间从3分钟缩短到不到10秒钟!

为了让这些数据更有参考价值:我的应用程序捆绑了额外的数据文件(大约150个文件,总大小为250MB),除了携带Qt和numpy(可能依赖于Intel MKL,这单独就增加了另外200MB的包大小!)依赖项。 即使测试系统使用固态硬盘运行,也没有什么太大帮助...

总之:如果您有一个具有许多依赖项的大型应用程序,则启动时间可能会受到杀毒系统的严重影响!


2

我通过向防病毒监控软件(F-Secure)添加异常解决了这个问题。这样就消除了运行前几分钟的等待时间。


Windows Defender也在这里。从几分钟到不到3秒钟。必须明确将其排除在扫描之外。 - wally

1
我遇到了相同的启动缓慢问题,最后我选择使用"--onedir"选项,但是在pyinstaller创建的分发文件夹上方创建了一个快捷方式,这样我就可以轻松找到可执行文件。
以下是批处理命令"build.bat"。

--

rem build with pyinstaller

C:\Python310\Scripts\pyinstaller.exe --onedir -w --noconfirm MyProg.py

rem create shortcut

set TARGET='C:\MyProgDir\dist\MyProg.exe'
set SHORTCUT='C:\MyProgDir\MyProg.exe.lnk'
set PWS=powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile
%PWS% -Command "$ws = New-Object -ComObject WScript.Shell; $s = $ws.CreateShortcut(%SHORTCUT%); $S.TargetPath = %TARGET%; $S.Save()"

0

我使用py2exe和cx_Freeze编译了几个wxPython应用程序,它们中没有一个需要超过4秒钟才能启动。

  • 你确定不是你的代码有问题吗?也许是一些网络或I/O资源调用阻塞了你的应用程序?
  • 你尝试过其他机器吗?即使最快的硬件有时候也会因为错误的软件配置、应用程序或操作系统而变慢,试试看。
  • 使用timeit模块计时。

我从未使用过pyQT,但是使用wxPython启动速度还可以,而且在第一次初始化后,如果我关闭并重新打开,它比第一次更快。


13
.exe文件及其依赖项和库到临时 (_MEIxxxx) 文件夹的解压缩是慢的,这发生在任何代码执行之前。即使是 print("Hello world!") 也需要10秒钟才能加载完毕。 - Guimoute

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