0

Whenever I get an error in my Tkinter application, I would like to get a full stack trace of where the error occurred, through all of the functions the program is currently in.

Before my root window opens, I have Tk.report_callback_exception = TKINTERERROR and I am able to get the traceback object of the error in TKINTERERROR(). However, when I attempt to print the traceback (with traceback.format_list(traceback.extract_tb(tracebackObject))), it only gives me the most recent function call, and the line the error occurred on. Is this all that is possible with Tkinter exceptions, or is there a way to get the entire stack trace?

To elaborate, what I expect to get is something like this, in which all the functions the program is currently in are given:

Traceback (most recent call last):
  File "myfilepath", line 13, in <module>
    func1()
  File "myfilepath", line 2, in func1
    func2()
  File "myfilepath", line 5, in func2
    func3()
  File "myfilepath", line 8, in func3
    func4()
  File "myfilepath", line 11, in func4
    0/0
ZeroDivisionError: division by zero

However, I actually only get this:

File "...Python311\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
File "myfilepath.py", line 1898, in <lambda>
    widgetMethod(arguments, command = lambda: MyFunction(arguments))
                                                                                                                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "myfilepath", line 2465, in MyFunction
    0/0
    ~^~

My problem is that I would like to get the full stack trace, but I am only given the most recent function called.

4
  • It works for me and shows the full error traceback after tkinter calls my function. What do you expect the traceback to look like? Can you give an example of what you are getting vs what you expect to get? On a side note, if you want to simplify your code a bit, use this. Commented Oct 11, 2023 at 15:40
  • It looks right to me. When you use a button command/.bind/.trace/.after, tkinter will call your code from inside the mainloop(). tkinter removes all of traceback that comes from you calling the .mainloop(). Right now it looks like you have a button which calls MyFunction with arguments and inside there you have are trying to divide by 0. Commented Oct 11, 2023 at 16:05
  • @TheLizzard That is correct. However, that window is created from another function call which also comes from a preceding function call, and those are not being displayed in the traceback. I know Tkinter does something with threading, is it that Tkinter only traces from the most recent .mainloop(), as my example is an error from a Toplevel() window? Commented Oct 11, 2023 at 16:17
  • tkinter does run from another thread. Also you should only have 1 .mainloop() in your code (no matter how many Tk()/Toplevel() widgets you have). Therefore, there's no point in showing the traceback for the .mainloop(). Commented Oct 11, 2023 at 17:14

1 Answer 1

0

This can be done by redefining the default TKINTERERROR() function:

from tkinter import *
import traceback

Tk.report_callback_exception = TKINTERERROR

#These arguments are supplied automatically and must be here
def TKINTERERROR(tkinterLibrary, errorClass, finalErrorMessage, tracebackObject):
     '''Prints stack trace of Tkinter error and enters Python debugger.'''
     print('\n' + str(errorClass) + ':\n' + traceback.format_exc() + '\n' + str(finalErrorMessage) + '\n')
     import pdb; pdb.post_mortem(tracebackObject)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.