2010-10-02 17 views
24

Pracuję nad biblioteką wysyłania wiadomości e-mail i chcę być w stanie przechwytywać wyjątki generowane przez nadawców (SMTP, Google AppEngine itp.) I zawijać je w łatwych do odczytywania wyjątków biblioteka (ConnectionError, MessageSendError itd.), z oryginalnym tracebackem nienaruszonym, aby można było debugować. Jaki jest najlepszy sposób to zrobić w Pythonie 2?Wyjątki od pakowania w języku Python

Odpowiedz

24

Najprostszym sposobem byłoby przebicie za pomocą starego obiektu śledzenia. Poniższy przykład pokazuje to:

import sys 

def a(): 
    def b(): 
     raise AssertionError("1") 
    b() 

try: 
    a() 
except AssertionError: # some specific exception you want to wrap 
    trace = sys.exc_info()[2] 
    raise Exception("error description"), None, trace 

Sprawdź dokumentację raise statement o szczegóły tych trzech parametrów. Mój przykład będzie drukować:

Traceback (most recent call last): 
    File "C:\...\test.py", line 9, in <module> 
    a() 
    File "C:\...\test.py", line 6, in a 
    b() 
    File "C:\...\test.py", line 5, in b 
    raise AssertionError("1") 
Exception: error description 

Dla kompletności w Pythonie 3 chcesz użyć raise MyException(...) from esyntax.

+1

'raise Exception (" opis błędu "), None, trace' ma skutek uboczny polegający na utracie oryginalnego komunikatu o błędzie. Ktoś wie, jak to obejść? –

+1

Skończyło się na tym, że korzystałem z wiadomości z oryginalnego wyjątku i łączę ją z nową wiadomością. –

+2

Wykonuję to w następujący sposób: 'raise Exception (" opis błędu \ nOprzez: {}: {} ".format (typ (e) .__ nazwa__, str (e))), Brak, sys.exc_info() [2 ] ' –

1

Ta odpowiedź jest prawdopodobnie nieco spóźniona, ale można zawinąć funkcję w postaci python decorator.

Oto prosty cheatsheet na temat różnych dekoratorów.

Oto przykładowy kod, jak to zrobić. Po prostu zmień decorator, aby wychwycić różne błędy na różne sposoby.

def decorator(wrapped_function): 
    def _wrapper(*args, **kwargs): 
     try: 
      # do something before the function call 
      result = wrapped_function(*args, **kwargs) 
      # do something after the function call 
     except TypeError: 
      print("TypeError") 
     except IndexError: 
      print("IndexError") 
     # return result 
    return _wrapper 


@decorator 
def type_error(): 
    return 1/'a' 

@decorator 
def index_error(): 
    return ['foo', 'bar'][5] 


type_error() 
index_error()