Exception handling in Tkinter
Question: So, I wrote a small Tkinter program in python. The program executes good, but
its easy for an exception to occur if theres a non-digit character entered
into a field.

so, I tried to remedy it, but my remedy fails:

and here is the issue:

    
    
    try:
                self.laborOne = float(self.trimmerOne_Entry.get()) * 8
                self.laborTwo = float(self.trimmerTwo_Entry.get()) * 8
                self.laborThree = float(self.operator_Entry.get()) * 8
                self.addedThem = self.laborOne + self.laborTwo + self.laborThree
                self.laborTotal.set(str(self.addedThem))
                self.perUnitLabor = self.addedThem / 125
                self.laborUnit.set(str(self.perUnitLabor))
    except ValueError:
            tkinter.messagebox.showinfo('Error:', 'One or more of your values was not numeric. Please fix them.')
            self.performIt()
                self.performIt()
    

At first I tried just showing the messagebox in the error handling, but that
closes the program when you click ok. SO, I tried recursion, calling the
function to itself. When this happens, the dialog box just stays there.
because self.performIt doesn't need an arg passed in, I passed (self) into it
just to try it. THIS allows me to fix my values in the boxes, which is what I
am looking for, but causes a different exception

Anyway, how can I handle the ValueError exception without the program
terminating, so that a user can enter corrected data?

Complete code

    
    
    import tkinter
    import tkinter.messagebox
    
    class MyGui:
        def __init__(self):
            #create the main window widget
            self.main_window = tkinter.Tk()
    
            #create 6 frames: 
            #one for each trimmers/operators pay,
            #one for buttons
            #one for outputs
            self.trimmerOne = tkinter.Frame(self.main_window)
            self.trimmerTwo = tkinter.Frame(self.main_window)
            self.operator = tkinter.Frame(self.main_window)
            self.rotaryLabor = tkinter.Frame(self.main_window)
            self.rotaryLaborUnit = tkinter.Frame(self.main_window)
            self.buttonFrame = tkinter.Frame(self.main_window)
    
            #create and pack widgets for Trimmer 1
            self.trimmerOne_Label = tkinter.Label(self.trimmerOne, text='Enter the payrate for trimmer 1: ')
            self.trimmerOne_Entry = tkinter.Entry(self.trimmerOne, width=10)
            self.trimmerOne_Label.pack(side='left')
            self.trimmerOne_Entry.pack(side='left')
    
            #create and pack widgets for Trimmer 2
            self.trimmerTwo_Label = tkinter.Label(self.trimmerTwo, text='Enter the payrate for trimmer 2: ')
            self.trimmerTwo_Entry = tkinter.Entry(self.trimmerTwo, width=10)
            self.trimmerTwo_Label.pack(side='left')
            self.trimmerTwo_Entry.pack(side='left')
    
            #create and pack widgets for Operator
            self.operator_Label = tkinter.Label(self.operator, text='Enter the payrate for operator: ')
            self.operator_Entry = tkinter.Entry(self.operator, width=10)
            self.operator_Label.pack(side='left')
            self.operator_Entry.pack(side='left')
    
            #create and pack widgets for rotaryLabor
            self.rotaryLabor_Label = tkinter.Label(self.rotaryLabor, text="This is what it cost's in trimmer labor: ")
            self.laborTotal = tkinter.StringVar() #to update with laborTotal_Label
            self.laborTotal_Label = tkinter.Label(self.rotaryLabor, textvariable=self.laborTotal)
            self.rotaryLabor_Label.pack(side='left')
            self.laborTotal_Label.pack(side='left')
    
            #create and pack widgets for labor Unit
            self.rotaryLaborUnit_Label = tkinter.Label(self.rotaryLaborUnit, text="This is the cost per part in trim labor: ")
            self.laborUnit = tkinter.StringVar() #to update with laborTotal_Label
            self.laborUnit_Label = tkinter.Label(self.rotaryLaborUnit, textvariable=self.laborUnit)
            self.rotaryLaborUnit_Label.pack(side='left')
            self.laborUnit_Label.pack(side='left')
    
            #create and pack the button widgets
            self.calcButton = tkinter.Button(self.buttonFrame, text = "Calculate", command=self.performIt)
            self.saveButton = tkinter.Button(self.buttonFrame, text = "Save", command=self.saveIt)
            self.quitButton = tkinter.Button(self.buttonFrame, text = "Quit", command=self.main_window.destroy)
            self.calcButton.pack(side="left")
            self.saveButton.pack(side="left")
            self.quitButton.pack(side="left")
    
            #pack the frames
            self.trimmerOne.pack()
            self.trimmerTwo.pack()
            self.operator.pack()
            self.rotaryLabor.pack()
            self.rotaryLaborUnit.pack()
            self.buttonFrame.pack()
    
            tkinter.mainloop()
    
        #define the function that will do the work:
        def performIt(self):
            try:
                self.laborOne = float(self.trimmerOne_Entry.get()) * 8
                self.laborTwo = float(self.trimmerTwo_Entry.get()) * 8
                self.laborThree = float(self.operator_Entry.get()) * 8
                self.addedThem = self.laborOne + self.laborTwo + self.laborThree
                self.laborTotal.set(str(self.addedThem))
                self.perUnitLabor = self.addedThem / 125
                self.laborUnit.set(str(self.perUnitLabor))
            except ValueError:
            tkinter.messagebox.showinfo('Error:', 'One or more of your values was not numeric. Please fix them.')
            self.performIt()
                self.performIt()
    
        def saveIt(self):
            self.laborOne = float(self.trimmerOne_Entry.get()) * 8
            self.laborTwo = float(self.trimmerTwo_Entry.get()) * 8
            self.laborThree = float(self.operator_Entry.get()) * 8
            self.addedThem = self.laborOne + self.laborTwo + self.laborThree
            self.laborTotal.set(str(self.addedThem))
            self.perUnitLabor = self.addedThem / 125
            self.laborUnit.set(str(self.perUnitLabor))
            file = open("log.txt", 'w')
            file.write("Trimmer One gets paid: " + str(self.laborOne))
            file.write("\n___________________________________________\n")
            file.write("Trimmer Two gets paid: " + str(self.laborTwo))
            file.write("\n___________________________________________\n")
            file.write("Operator gets paid: " + str(self.laborThree))
            file.write("\n___________________________________________\n")
            file.write("The sum of thier daily labor is: " + str(self.addedThem))
            file.write("\n___________________________________________\n")
            file.write("If production is reached, the labor cost is" + str(self.laborOne) + "per unit")
            file.write("\n___________________________________________\n")
            file.close()
    
    
    
    testRun = MyGui()
    


Answer: That's not how you catch errors. Do it like this:

    
    
    except ValueError:
                tkinter.messagebox.showinfo('Error:', 'One or more of your values was not numeric. Please fix them.')
    

You don't need to call the function again.

