使用Python在Tkinter中保存异常

使用Python在Tkinter中保存异常,python,tkinter,Python,Tkinter,我已经为其他使用Tkinter接收用户输入的程序开发了几个Python程序。为了保持简单和用户友好,命令行或python控制台从未启动(即使用pyw文件),因此我正在研究在发生异常时使用日志库将错误文本写入文件。但是,我很难让它真正捕获异常。例如: import tkinter as tk def handle_exception(exception, value, traceback): print("Caught exception:", exception) def raise

我已经为其他使用Tkinter接收用户输入的程序开发了几个Python程序。为了保持简单和用户友好,命令行或python控制台从未启动(即使用pyw文件),因此我正在研究在发生异常时使用日志库将错误文本写入文件。但是,我很难让它真正捕获异常。例如:

import tkinter as tk

def handle_exception(exception, value, traceback):
    print("Caught exception:", exception)

def raise_error():
    raise Exception("Sad trombone!")

root = tk.Tk()
# setup custom exception handling
root.report_callback_exception=handle_exception

# create button that causes exception
b = tk.Button(root, text="Generate Exception", command=raise_error)
b.pack(padx=20, pady=20)

root.mainloop()
我们编写了一个会导致错误的函数:

def cause_an_error():
    a = 3/0
现在我们尝试正常记录错误:

import logging
logging.basicConfig(filename='errors.log', level=logging.ERROR)

try:
    cause_an_error()
except:
    logging.exception('simple-exception')
正如预期的那样,程序会出错,日志会将错误写入errors.log。控制台中没有显示任何内容。但是,当我们实现Tkinter接口时,会产生不同的结果,如下所示:

import logging
import Tkinter
logging.basicConfig(filename='errors.log', level=logging.ERROR)

try:
    root = Tkinter.Tk()
    Tkinter.Button(root, text='Test', command=cause_an_error).pack()
    root.mainloop()
except:
    logging.exception('simple-exception')
在这种情况下,按下Tkinter窗口中的按钮会导致错误。但是,这次不会向文件写入任何内容,控制台中会出现以下错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1536, in __call__
    return self.func(*args)
  File "C:/Users/samk/Documents/GitHub/sandbox/sandbox2.pyw", line 8, in cause_an_error
    a = 3/0
ZeroDivisionError: integer division or modulo by zero

是否有其他方法来捕获和记录此错误?

没有很好的文档记录,但是tkinter调用了一个方法来处理回调导致的异常。通过在根窗口上设置属性
report\u callback\u exception
,您可以编写自己的方法来执行任何操作

例如:

import tkinter as tk

def handle_exception(exception, value, traceback):
    print("Caught exception:", exception)

def raise_error():
    raise Exception("Sad trombone!")

root = tk.Tk()
# setup custom exception handling
root.report_callback_exception=handle_exception

# create button that causes exception
b = tk.Button(root, text="Generate Exception", command=raise_error)
b.pack(padx=20, pady=20)

root.mainloop()
供参考:


Tkinter在自己的线程上运行,并且只有在关闭窗口后才会执行
root.mainloop
之后的所有操作。还要注意的是,只有在单击按钮时才会执行
cause\u错误
,但首先执行
root.mainloop
。可能发生的情况是,异常没有被捕获,因为它是在一个不同的“环境”中抛出的……我希望有人能给出一个更详细和技术性的答案。有趣。既然您提到了它,“raise”命令也无法检索错误,因此它看起来肯定是在不同的环境中抛出的。有没有一种方法可以在我导入Tkinter之后修改Tkinter对错误的处理以包括日志记录?通过这种方法,您可以直接在函数中捕获异常……是的,这是绝对正确的。我希望有一个比将每个函数封装在try/except语句中更优雅的解决方案,尤其是在一个有很多函数的更复杂的程序中。太好了,谢谢!)有没有办法检索产生异常的行号或函数?@SamKrygsheld:看看
traceback
参数。啊,是的,谢谢。对于将来可能看到这一点的人,我假设传入的回溯是一个字符串,但实际上是一个回溯对象。使用traceback.tb_lineno将允许您访问行号。