【问题标题】:Saving exceptions in Tkinter using Python使用 Python 在 Tkinter 中保存异常
【发布时间】:2016-07-20 20:11:20
【问题描述】:

我为使用 Tkinter 接收用户输入的其他人开发了几个 Python 程序。为了保持简单和用户友好,命令行或 python 控制台永远不会出现(即使用 .pyw 文件),所以我正在研究使用日志库将错误文本写入文件时发生异常。但是,我很难让它真正捕捉到异常。例如:

我们写了一个会导致错误的函数:

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 在自己的线程上运行,root.mainloop 之后的所有内容只有在您关闭窗口后才会执行。另请注意,cause_an_error 仅在您单击按钮时才会执行,但首先会执行 root.mainloop。发生的事情可能是没有捕获异常,因为它被抛出在不同的“环境”中......我希望有人提出更详细和技术性的答案。
  • 有趣。既然你提到了它,“raise”命令也无法检索错误,所以它肯定似乎是在不同的环境中抛出的。有没有办法可以修改 Tkinter 对错误的处理以在导入后包含日志记录?
  • 你可以直接在函数中捕获异常...
  • 是的,这绝对是真的。我希望有一个比将每个函数都包含在 try/except 语句中更优雅的解决方案——尤其是在一个具有很多函数的复杂得多的程序中。

标签: python tkinter


【解决方案1】:

它的文档记录不是很好,但是 tkinter 调用一个方法来处理由于回调而发生的异常。通过在根窗口上设置属性report_callback_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()

供参考:

【讨论】:

  • 完美,谢谢! :) 有什么方法可以检索产生异常的行号或函数?
  • @SamKrygsheld:看看traceback 参数。
  • 啊,是的,谢谢。对于将来可能会看到这一点的任何人,我假设传入的回溯是一个字符串,但它实际上是一个回溯对象。使用 traceback.tb_lineno 将允许您访问行号。
猜你喜欢
  • 2017-04-27
  • 1970-01-01
  • 1970-01-01
  • 2010-12-15
  • 1970-01-01
  • 1970-01-01
  • 2013-01-05
  • 1970-01-01
  • 2020-09-16
相关资源
最近更新 更多