The event loop started by calling
.exec_() on your
object runs within the same thread as your Python code. The thread
which runs this event loop — commonly referred to as the GUI thread —
also handles all window communication with the host operating system.
By default, any execution triggered by the event loop will also run synchronously within this thread. In practice this means that any time your PyQt application spends doing something in your code, window communication and GUI interaction are frozen.
If what you're doing is simple, and returns control to the GUI loop quickly, this freeze will be imperceptible to the user. However, if you need to perform longer-running tasks, for example opening/writing a large file, downloading some data, or rendering some complex image, there are going to be problems. To your user the application will appear to be unresponsive. Because your app is no longer communicating with the OS the OS will think it has crashed -- on macOS you see the spinning wheel of death, on Windows the window will dim. That's not a good look.
The solution is simple -- get your work out of the GUI thread. PyQt provides straightforward interfaces to accomplish exactly that.