1

Currently I am working on a GUI application that is developed in PyQt.

The functionality of this GUI contains several threads. I assume this is the reason that when I simply click the red x in the corner of the window.

It doesn't fully close the process (despite the visual aspect of the GUI disappearing).

Is there a way I can link the x in the main window to a close function that stops all threads?

I am new to PyQt so go easy on me! (Also, I believe all of my threads are Python threads, not Qthreads)

Bhavesh Odedra
  • 10,990
  • 12
  • 33
  • 58
sudobangbang
  • 1,406
  • 10
  • 32
  • 55
  • That question does not have the solution to how to fully kill the endless processes going on. – sudobangbang Jul 01 '14 at 11:55
  • The one starting the processes is usually responsible for stopping them. So if you are the one only you know how to stop them. If QT started some processes and is used correctly it will stop all processes and you don't need to worry. This part of your question cannot be answered in general without any code. The core part of the question reduces to how to intercept the closing event and start manual clean up which you have to do yourself or show some code. The linked question answers the core part quite well in my opinion. – NoDataDumpNoContribution Jul 01 '14 at 13:39

1 Answers1

1

You can just set the daemon flag on the Thread objects to True prior to starting the threads. As stated in the documentation:

A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left. The initial value is inherited from the creating thread. The flag can be set through the daemon property.

It's also worth noting that this is potentially dangerous, depending on what your background threads are doing (again, quoting the documentation):

Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signalling mechanism such as an Event.

The way you implement a graceful shutdown is somewhat dependent on how your threaded code is implemented, but it would look something like this:

Thread method:

def threaded_method(event, ...):
    while True:
       if event.is_set()
           # clean up
           return
       # Normal stuff it does goes here.

Main thread:

def on_exit(): # called when X in main window pressed
    event.set() # Tell threads to cleanup.
    # Do normal exit stuff.

if __name__ == "__main__":
    event = threading.Event()
    t = threading.Thread(target=threaded_method, args=(event, ...))
    #t.daemon = True # Assuming you don't care about gracefully stopping the threads, you can just do this and leave out the Event stuff.
    t.start()
    # other stuff

Note that it's possible that this approach may not work, if the loop in your thread is blocking on something (like getting data from a sub-process) that doesn't unblock when your program exits. Let me know if that's the case and I can probably rework my answer to cover that.

dano
  • 91,354
  • 19
  • 222
  • 219