简体   繁体   English

Python:如何以其他方式处理任何未处理的异常?

[英]Python: how can I handle any unhandled exception in an alternative way?

Normally unhandled exceptions go to the stdout (or stderr?), I am building an app where I want to pass this info to the GUI before shutting down and display it to the user and, at the same time I want to write it to a log file. 通常未处理的异常会传到stdout(或stderr?),我正在构建一个应用,我想在将此信息传递给GUI之前将其关闭并显示给用户,同时,我想将其写入到日志文件。 So, I need an str with the full text of the exception. 因此,我需要一个带有异常全文的str。

How can I do this? 我怎样才能做到这一点?

Use sys.excepthook to replace the base exception handler. 使用sys.excepthook替换基本异常处理程序。 You can do something like: 您可以执行以下操作:

import sys
from PyQt4 import QtGui

import os.path
import traceback

def handle_exception(exc_type, exc_value, exc_traceback):
  """ handle all exceptions """

  ## KeyboardInterrupt is a special case.
  ## We don't raise the error dialog when it occurs.
  if issubclass(exc_type, KeyboardInterrupt):
    if QtGui.qApp:
      QtGui.qApp.quit()
    return

  filename, line, dummy, dummy = traceback.extract_tb( exc_traceback ).pop()
  filename = os.path.basename( filename )
  error    = "%s: %s" % ( exc_type.__name__, exc_value )

  QtGui.QMessageBox.critical(None,"Error",
    "<html>A critical error has occured.<br/> "
  + "<b>%s</b><br/><br/>" % error
  + "It occurred at <b>line %d</b> of file <b>%s</b>.<br/>" % (line, filename)
  + "</html>")

  print "Closed due to an error. This is the full error report:"
  print
  print "".join(traceback.format_exception(exc_type, exc_value, exc_traceback))
  sys.exit(1)



# install handler for exceptions
sys.excepthook = handle_exception

This catches all unhandled exceptions, so you don't need a try...except block at the top level of your code. 这会捕获所有未处理的异常,因此您不需要在代码顶层尝试try ... except块。

You already got excellent answers, I just wanted to add one more tip that's served me well over the years in a variety of language for the specific problem "how to cleanly diagnose, log, etc, out of memory errors?". 您已经得到了很好的答案,我只是想再添加一个小技巧,这些小技巧多年来用多种语言针对特定问题“如何彻底诊断,记录等, out of memory错误?”为我服务。 Problem is, if your code gets control before enough objects have been destroyed and their memory recycled, memory might be too tight to do propert logging, gui work, etc, etc -- how do we ensure this doesn't happen? 问题是,如果您的代码在销毁了足够多的对象并回收它们的内存之前就获得了控制,则内存可能太紧而无法进行属性记录,GUI工作等,我们如何确保不会发生这种情况?

Answer: build an emergency stash so you know you can spend it in such emergencies: 答案:建立应急仓库,以便您知道可以在以下紧急情况下使用它:

rainydayfund = [[] for x in xrange(16*1024)]  # or however much you need

def handle_exception(e):
  global rainydayfund
  del rainydayfund
  ... etc, etc ...
import sys, logging

logging.basicConfig(filename='/path/to/log/file', filemode='w')    
...

try:
   your_code_here()
except:
   logging.exception("My code failed") # logs exception to file
   # you define display_exception_in_ui as "def display_exception_in_ui(exc, tb):"
   display_exception_in_ui(*sys.exc_info()[1:]) # passes exception instance, traceback
try:
    # blah blah The Main Loop, function, whatever...
except e:
    do_something_with(str(e))

I tried using Neil's answer , but it doesn't work with a Tkinter GUI. 我尝试使用Neil的答案 ,但是它不适用于Tkinter GUI。 For that, I had to override report_callback_exception() . 为此,我不得不重写report_callback_exception()

import Tkinter as tk
import tkMessageBox
import traceback

class MyApp(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        parent.report_callback_exception = self.report_callback_exception
        self.parent = parent
        self.button_frame = tk.Frame(self)
        self.button_frame.pack(side='top')
        self.button_run = tk.Button(
            self.button_frame, text="Run", command=self.run
        )
        self.button_run.grid(row=0, column=1, sticky='W')

    def run(self):
        tkMessageBox.showinfo('Info', 'The process is running.')
        raise RuntimeError('Tripped.')

    def report_callback_exception(self, exc_type, exc_value, exc_traceback):
        message = ''.join(traceback.format_exception(exc_type,
                                                     exc_value,
                                                     exc_traceback))
        tkMessageBox.showerror('Error', message)

def main():
    root = tk.Tk()  # parent widget

    MyApp(root).pack(fill='both', expand=True)

    root.mainloop()  # enter Tk event loop

if __name__ == '__main__':
    main()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM