Search code examples
pythontkinterjupyter-notebookexit

Using Jupyter notebook - which is best for this tkinter algrithm? quit(), exit(), sys.exit(), or os.exit()?


I am using the Jupyter notebook to write a tkinter algorithm with a lot of "if" statements.

I would like some of these "if" statements to stop running the program (but not stop the tkinter window from running) at certain points without returning to the main flow of the code. I wrote a small sample app (below) to illustrate what I mean.

I have tried using quit(), exit(), sys.exit(), and os.exit(). Both quit() and exit() seem to work okay,They say "Hi" and not "bye", as expected. But I still get some unwanted readout when I close the tkinter window - which I think may be more Jupyters fault than python or tkinter. It usually says, "The kernel appears to have died. It will restart automatically."

The sample script contains each of the commands above, and it uses a comment "#" to toggle the line on and off. The unwanted readout and messages for each case are also commented beside the code in the script.

My concern is whether the unwanted readout could be problematic or even a security threat if I code any further, since some of these if statements will be used in a password protected area. Would I be correct in assuming, if the unwanted messages came from Jupyter, the messages will be benign and transparent once I compile the code to an exe?

My code is below:

import tkinter
from tkinter import * 
import tkinter as tk

import sys
import os

def routine ():
    
    x = 0

    if x < 1:

        print("Hi")

    # quit()  # Prints Hi and not bye; 
              # when destroyed, it says Kernel Restarting
              # The kernel appears to have died. It will restart automatically.
            
    # exit()  # On an apparent level - it seems to do all the same things as quit.
    
    # sys.exit()    # Prints Hi
                    # and then...
                    # An exception has occurred, use %tb to see the full traceback.
                    # SystemExit
                    # Then the entire systems, including the tkinter window, 
                    # locks up and spin doing nothing.
                    # The close button wont even work.

    # os._exit()  # Exception in Tkinter callback
                # Traceback (most recent call last):
                # File "C:\Users\rrr\lib\tkinter\__init__.py", line 1705, in __call__
                # return self.func(*args)
                # File "<ipython-input-3-c9d340ae6a31>", line 31, in routine
                # os._exit()
                # TypeError: _exit() missing required argument 'status' (pos 1)

    if x > 1:

        print("bye...")


root = Tk()  
root.geometry("300x200+200+200")

btn1 = Button(root, text ="Run A Routine", command = routine)
btn1.pack(pady = 20, anchor='center')

btn1 = Button(root, text ="Close Window", command = root.destroy)
btn1.pack(pady = 20, anchor='center')

root.mainloop()

Solution

  • I am wondering what you mean by "stop running the program"? Do you mean exit the function/subroutine that you have written? Because if that is the case, you should simply use return to exit the defined routine.

    If you want to do something more complex, you may need to remove your .mainloop() call for updating tkinter, and instead use something like the below:

    RUN_FLAG = True
    while RUN_FLAG:
        root.update_idletasks()
        root.update()
        time.sleep(0.01)
    

    This would allow you to update the global variable RUN_FLAG in your subroutine and use that to move beyond your tkinter and then finish your script.

    Also, side note; Running tkinter in Jupyter is a bit odd, in my opinion. If your solution gets much more extensive, you'd probably get better performance from a standard python script. I recommend "PyCharm" by JetBrains as an IDE.