使用Python在Tkinter中保存异常
我为其他使用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调用了一个方法来处理回调结果中出现的异常。通过在根窗口上设置属性
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()
由于这个问题是关于日志记录和明确错误发生的地方,我将扩展到Bryan (完全正确的)答案。
首先,您必须导入一些其他有用的模块。
import logging import functools # for the logging decorator import traceback # for printing the traceback to the log
然后,您必须配置记录器和日志功能:
logging.basicConfig(filename='/full/path/to_your/app.log', filemode='w', level=logging.INFO, format='%(levelname)s: %(message)s') def log(func): # logging decorator @functools.wraps(func) def wrapper_log(*args, **kwargs): msg = ' '.join(map(str, args)) level = kwargs.get('level', logging.INFO) if level == logging.INFO: logging.info(msg) elif level == logging.ERROR: logging.exception(msg) traceback.print_exc() return wrapper_log @log def print_to_log(s): pass
注意,进行日志记录的函数实际上是log
,您可以将它用于打印错误和日志文件中的常规信息。如何使用它:使用用print_to_log
修饰的函数log
。而不是pass
,您可以放置一些常规的print()
,以便将消息保存到日志中,并将其打印到控制台。您可以用您喜欢的任何命令替换pass
。
注nb.2我们使用log
函数中的回溯来跟踪代码到底在哪里生成错误。
若要处理异常,请按照已接受的答案进行处理。此外,您还将消息(即跟踪)传递给print_to_log
函数:
def handle_exception(exc_type, exc_value, exc_traceback): # prints traceback in the log message = ''.join(traceback.format_exception(exc_type, exc_value, exc_traceback)) print_to_log(message)
在配置了所有这些之后,现在您告诉您的Tkinter应用程序它必须使用handle_exception
函数:
class App(tk.Tk): # [the rest of your app code] if __name__ == '__main__': app = App() app.report_callback_exception = handle_exception app.mainloop()
或者,如果您使用多个类,甚至可以指示类本身使用andle_exception
函数:
class App(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) tk.Tk.report_callback_exception = handle_exception # [the rest of your app code] if __name__ == '__main__': app = App() app.mainloop()
通过这种方式,您的应用程序代码看起来很简洁,您不需要任何尝试/除方法,并且您可以在信息级别记录您的应用程序中的任何事件。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2018-11-24 Android性能优化之图片压缩优化
2018-11-24 Android应用开发中三种常见的图片压缩方法
2018-11-24 Android组件化和插件化开发