Manually managing QThread instances is somewhat painful. What I found useful is using the global QThreadPool that is managed by Qt. Have a look at QThreadPool.globalInstance(), which gives you the global thread pool available in any Qt application. Then you can submit long running tasks as QRunnable instances into the pool to run in the background.
It is meant for "run and forget" type tasks, so cancelling and status/progress reporting has to be implemented yourself.
For the progress indicator, I went with a simple ProgressSignalContainer class (derived from QObject) that simply contains the signal definitions required for progress reporting. The task to run is subclassed from QRunnable (which is not derived from QObject and thus can't have Qt Signals), and sets up a signal container in __init__. After instantiation, connect the signals, and then submit the runnable instance to the thread pool.
You probably want to store the Python object reference somewhere though.
13 July 2024