App created with PyInstaller has a slow startup - python

I have an application written in Python and 'compiled' with PyInstaller. It also uses PyQt for the GUI framework.
Running this application has a delay of about 10 seconds before the main window loads and is shown. As far as I can tell, this is not due to slowness in my code. Instead, I suspect this is due to the Python runtime initializing.
The problem is that this application is started with a custom laucncher / taskbar application. The user will click the button to launch the app, see nothing appear to happen, and click elsewhere on another application. When my application shows it's window, it cannot come to the foreground due to the rules for SetForegroundWindow.
I have access to the source for the PyInstaller win32 loader, the Python code, and even the launcher code.
My questions are:
How can I make this application start faster?
How can I measure the time spend i the first few seconds of the process's lifetime?
What is the generally accepted technique for reducing time until the first window is shown?
I'd like to avoid adding a splash screen for two reasons - one, I expect it won't help (the overhead is before Python code runs) and two, I just don't like splash screens :)
If I need to, I could probably edit the PyInstaller loader stub to create a window, but that's another route i'd rather not take.

I suspect that you're using pyinstaller's "one file" mode -- this mode means that it has to unpack all of the libraries to a temporary directory before the app can start. In the case of Qt, these libraries are quite large and take a few seconds to decompress. Try using the "one directory" mode and see if that helps?

Tell PyInstaller to create a console-mode executable. This gives you a working console you can use for debugging.
At the top of your main script, even before the first import is run, add a print "Python Code starting". Then run your packaged executable from the command line. This way you can get a clear picture whether the time is spent in PyInstaller's bootloader or in your application.
PyInstaller's bootloader is usually quite fast in one-dir mode, but it can be much slower in one-file mode, because it depacks everything into a temporary directory. On Windows, I/O is very slow, and then you have antiviruses that will want to double check all those DLL files.
PyQt itself is a non-issue. PyQt is generated by SIP which generates very fast lazy bindings; importing the whole PyQt is faster than any other GUI library because it basically does nothing: all bindings to classes/functions are dynamically created when (and if!) you access them, saving lots of memory too.
If your application is slow at coming up, that will be true without PyInstaller as well. In that case, your only solution is either a splash screen (import just PyQt, create QApplication, create a display the splashscreen, then import the rest of your program and run it), or rework your code. I can't help you much without details.

I agree with above answers. My Qt python program needed about 5 seconds to start up on a decent PC when using onefile mode. After I change to --onedir, it only took around one second to start; almost immediately after user double clicks the exe file. But the drawback is that there are many files in that directory which is not so neat.

For my application, the long startup time almost entirely was caused by the antivirus system. Switching it off reduced the startup in my case from 3 minutes to less than 10secs!
To bring these measurements into perspective: My application was bundled with extra data files (about 150 files with a payload of 250MB), besides carrying around Qt and numpy (that may depend on Intel MKL, which alone adds another 200MB to the bundle!) dependencies. It even didn't help much that the tested system was running with a solid state drive...
In conclusion: if you have a large application with lots of dependencies, the startup time may be affected strongly by the antivirus system!

In case anyone is still have this issue, I resolved mine by running the exe locally and not on any sharedrives. This took the startup time from over a minute to under 10 seconds.

I solved this by adding an exception to the anti-virus monitoring software (F-Secure). It removed the wait of several minutes before running.

I have 'compiled' a few wxPython apps using py2exe and cx_Freeze, None of them take more than 4 seconds to start.
Are you sure sure it's not your code ?
maybe some network or some I/O resource call holding your app ?
Have you tried other machine than yours? Even the fastest hardware can be slow sometimes with the wrong software config, apps or OS, try it.
Try timing it with timeit module.
I never used pyQT, but with wxPython the startup speed is OK, and after the first initialize if I close and open again, it's faster than the first time.

Related

Python curses window flickering when resizing terminal

This is my first post on stack overflow so I hope I'm doing it properly.
I am currently working on a Terminal User Interface for python applications. I know that there are many ready-to-use libraries such as npyscreen out there, but I wantend to create one as programming excercice. In particular, I wanted to to play with some architectural patterns to learn them.
All that said, I'm currently facing several problems with python curses library, that I'm using as low level interface to the terminal.
The problems arise when I try to resize my terminal. As you can see from the code (see below), I handle the terminal resizing in the main loop, invoking the getmaxyx()() method of my curses window and redrawing what is on the screen accordingly.
The problem is that the screen seems to flicker when I try to resize the terminal.
Moreover, my "curses application" works fine on MacOS but totally crashes on windows (even after installing windows curses).
To handle that I tried to re-write the low-level interfice by using the blessed library. It solved the windows crashing problem, but the flickering still remains.
I can not figure out what the problem is.
Fore those wishing to help me, here follows the github page of the project: Terminal GUI on GitHub
Thank you in advance.
With curses, there's (at least) 3 things to look for:
ncurses can handle SIGWINCH (PDCurses may not)
some Python configurations interfere with ncurses receiving SIGWINCH. If your program never receives KEY_RESIZE (which it's not checking for...), then it's time to file a bug report for Python to get that fixed.
some programs don't actively read keyboard input (and if KEY_RESIZE isn't read, ncurses won't update the screensize. That would make the program crash.

Launch times of compiled Python vs IronPython

I'm currently writing some Windows GUI applications in Python 2.7 using pyQT4 and pyInstaller. These compiled executables are taking about 3-6 seconds to open. I've eliminated UPX already and seen some time shaved off the load, and some more by not packaging it as a single exe but I'd rather have a single distributable file.
I was wondering if IronPython would be a better at providing a quick loading application. Or any of the other version of Python, or better yet if there is anything else i can do to minimize the wait for the GUI to be drawn on the screen.
IronPython does add a performance hit to a number of specific areas compared to Python. However, I would not draw the conclusion that it is always slower. There has been a post already on that topic Why is IronPython faster than the Official Python Interpreter
The most important aspect to consider is have you fully optimized everything in your Python project? As in, have you performed any code profiling?
If the answer is yes then you could attempt to migrate to a different toolkit or language. If you chose IronPython (link) it would be wise to migrate your GUI to .NET (winforms, XAML, etc). Another option (albeit unpopular to most) would be to use tkinter. Tkinter is very powerful in that one can fully-customize the code to be nothing more and nothing less than the project requires. Of course that will add considerable typing time. But I have made Python apps that load and draw a window almost immediately and quite honestly almost looked like it came out of VS2012.

Frozen Python Application with cx_Freeze is very slow to start

I have a fairly complex python application that uses numpy, pandas, PySide, pyqtgraph, and matplotlib, among other packages. When I bundle the application with cx_Freeze on Windows, it comes in at 349MB.
My problem is the resulting executable has a very long startup time of about 15 seconds. When I say startup time, I mean the amount of time before any code gets executed. I have a simple script that prints "Hello" to the console, and even that takes about 15 seconds to run.
Does anyone know of a solution to this problem, or any ways to debug it? Is it slow because there are so many .dll files from so many packages?
EDIT:
Using a great tool called Process Montor, I have narrowed down my problem to the pytz module. On one particular load, 20 seconds were spent querying the library.zip (where cx_Freeze puts all of the compiled bytecode) for pytz zoneinfo! I recently added pandas as a dependency, and pandas uses pytz.
See this picture for a sampling of the Process Monitor output:
The solution I found is to use Process Monitor to see if cx_Freeze is loading a module for an unreasonable amount of time. Using that tool, I also found that it was taking a long time (maybe 4 seconds) to load a particular matplotlib font. I removed it and my application worked fine.

Detecting active windows in python with KDE

I'm writing a small python script that tracks how I'm dividing my time between programs. It needs to detect the currently active window (ideally, the application controlling that window, but I can make do with just the window title), as well as idle time.
At the moment, I'm using KIdleTime to determine how long I've been not touching my computer, which works fine by itself.
I also try to use wnck to determine which windows are active, and again, this works fine by itself.
It's when I try to combine the two into one program that I run into troubles. Since wnck is a gnome library and KIdleTime is a KDE library, they need to be run on their own threads for the window change and idle timeout signals to fire.
I'm having trouble finding a way to do this in python - if I use the threading module to try to run one of them on a separate thread, the KDE library complains that it's not on the main thread, or the Gnome library has an impressive meltdown and eats all the memory it can get (incidentally, ulimit was very useful in this case, I can recommend it).
So, I have four options:
Find a KDE library that can detect
when the window is changed - I would
have thought that dbus would expose
this in kwin, but it doesn't seem
to.
Find a way of running both the kde and gnome libraries at the same
time.
Find an equivalent of KIdleTime that runs on the Gnome event thread.
Use timers to poll KIdleTime from within the Gnome thread (which is
what I'm doing now, but is far from ideal, it leads to imprecision in
determining idle times).
Can anyone offer me a solution?
One can use the wxPython GUI toolkit for this purpose.
It has a method for getting the active window.
It has a timer class, althou there are multiple ways you could use.
Of course, you can forget about QT, Gnome, and all other graphical libraries.
Here is what wx can do.

Why is PyQt application startup so slow?

C++ is fast. Qt is fast. Python interpreter startup is relatively fast (2-3 seconds on my computer). PyQt is thin wrapper around Qt. Why then PyQt app startup (about 80 lines, even in .pyc form) is so slow (6-12 seconds)? I'm interested in reasons for this and, most importantly, ways to improve this situation.
There is a known bug in Qt 4.6.3 that cripples application start times. Maybe 4.4.3 is also affected. Try to upgrade to 4.7.0, which fixes that bug.
Your problem might also come from dynamic library relocation. If you compile either Qt or Python yourself, try to give them a base address different from the default (0x10000000), to prevent relocation to occur when the two libraries are loaded together.
Under Linux, you could have used prelink, but to my knowledge it has no equivalent on Windows.

Categories