Python: как я могу обработать любое необработанное исключение альтернативным способом? - PullRequest
6 голосов
/ 05 августа 2009

Обычно необработанные исключения идут в stdout (или stderr?), Я создаю приложение, в котором я хочу передать эту информацию в графический интерфейс перед выключением и отобразить ее пользователю, и в то же время я хочу написать это в лог-файл. Итак, мне нужна строка с полным текстом исключения.

Как я могу это сделать?

Ответы [ 5 ]

16 голосов
/ 06 августа 2009

Используйте sys.excepthook для замены базового обработчика исключений. Вы можете сделать что-то вроде:

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

Это ловит все необработанные исключения, поэтому вам не нужно пытаться ... кроме блока на верхнем уровне вашего кода.

9 голосов
/ 06 августа 2009

У вас уже есть отличные ответы, я просто хотел добавить еще один совет, который хорошо мне помогал на протяжении многих лет на разных языках для конкретной проблемы «как правильно диагностировать, регистрировать и т. Д., out of memory ошибки?». Проблема в том, что если ваш код получает контроль до того, как будет уничтожено достаточное количество объектов и их память будет перезаписана, память может быть слишком тесной, чтобы выполнять запись в журнал, работу с графическим интерфейсом и т. Д. И т. Д.

Ответ: создайте запасной запас, чтобы вы знали, что можете потратить его в таких чрезвычайных ситуациях:

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

def handle_exception(e):
  global rainydayfund
  del rainydayfund
  ... etc, etc ...
2 голосов
/ 06 августа 2009
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
0 голосов
/ 24 августа 2015

Я пытался использовать ответ Нейла , но он не работает с графическим интерфейсом Tkinter. Для этого мне пришлось переопределить 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()
0 голосов
/ 05 августа 2009
try:
    # blah blah The Main Loop, function, whatever...
except e:
    do_something_with(str(e))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...