Search code examples
pythonmatplotlibtkinterpyinstaller

Tkinter-based app keeps running in the background if the window is closed abruptly


I've created a tkinter app designed to let users create and take quizzes locally. Unfortunately, if a user closes the window by hitting the 'x' in the corner instead of hitting the "quit" button on the main menu, the window is destroyed but the process remains in the background. It isn't a huge deal as it stops using any CPU and only holds on to about 40mb of memory per instance, but this just seems pretty sloppy for an app that I'd like to deploy.

I have no idea what specifically is refusing to exit when the window is closed, and as it could be coming from almost anywhere in my 1700 lines of code, I'm instead looking for some more general tips for identifying what's still running or for killing any remaining processes when the window is closed. I'm happy to provide my code if anyone thinks it would help, though I reiterate that it's quite long given that I can't identify the source of the particular problem.


Solution

  • I believe this is the exact solution to your question. I read this thread before finding the solution, so I thought it would be good to contribute. The quit method and destroy methods did not work for me. Instead, I obtained the process ID (PID) for the main program and any subprocesses generated. I have included a snipping of how I implemented this so that all processes closed when I pressed the exit window button in Linux. Its a class called 'Moisure' using custom tkinter where process objects generated called P and L (for my plotter and logger processes) called inside were obtained to kill. Your program should finish the if statement upon closing. The 'try' statement is in case I never started those processes. This has not been tested on any other operating, but it should work on windows as well but Ive read packaging as an exe has fixed this.

    import os, signal
    
    if __name__ == "__main__":
        app = Moisture()
        app.mainloop()
        try:
            app.P.kill()
        except:
            pass
        try:
            app.L.kill()
        except:
            pass
        PID = os.getpid()
        os.kill(PID, signal.SIGKILL) 
    

    Also, I haven't seen your code but I suggest using try and except methods in various ways to ensure that your program doesn't close prematurely and leave any subprocesses running in the background if you're running any. Hopefully it helps you and anyone else too!!!