przechwytywanie wiadomości wyjątku python


519
import ftplib
import urllib2
import os
import logging
logger = logging.getLogger('ftpuploader')
hdlr = logging.FileHandler('ftplog.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)
FTPADDR = "some ftp address"

def upload_to_ftp(con, filepath):
    try:
        f = open(filepath,'rb')                # file to send
        con.storbinary('STOR '+ filepath, f)         # Send the file
        f.close()                                # Close file and FTP
        logger.info('File successfully uploaded to '+ FTPADDR)
    except, e:
        logger.error('Failed to upload to ftp: '+ str(e))

Wydaje się, że to nie działa, pojawia się błąd składniowy, jaki jest prawidłowy sposób rejestrowania wszelkiego rodzaju wyjątków w pliku


2
Twoje wcięcie jest zepsute. I pomiń ,później except.
— Sven Marnach

3
@ SvvenMarnach, jeśli pominiesz ,później except, otrzymasz global name 'e' is not defined, co nie jest dużo lepsze niż zła składnia.
— Val

12
@Val: Powinien być except Exception as elub except Exception, e, w zależności od wersji Python.
— Sven Marnach,

1
Prawdopodobnie jest to gdzieś w pobliżu tych 8 odpowiedzi, ale kiedy otwierasz plik, zamknięta część nigdy nie powinna znajdować się w instrukcji try, ale albo w instrukcji last, albo w instrukcji with.
— JC Rocamonde

Odpowiedzi:


733

Musisz zdefiniować typ wyjątku, który chcesz złapać. Napisz więc except Exception, e:zamiast except, e:ogólnego wyjątku (który i tak zostanie zarejestrowany).

Inną możliwością jest napisanie w ten sposób całego kodu try / oprócz:

try:
    with open(filepath,'rb') as f:
        con.storbinary('STOR '+ filepath, f)
    logger.info('File successfully uploaded to '+ FTPADDR)
except Exception, e: # work on python 2.x
    logger.error('Failed to upload to ftp: '+ str(e))

w Pythonie 3.xi współczesnych wersjach Pythona 2.x except Exception as ezamiast except Exception, e:

try:
    with open(filepath,'rb') as f:
        con.storbinary('STOR '+ filepath, f)
    logger.info('File successfully uploaded to '+ FTPADDR)
except Exception as e: # work on python 3.x
    logger.error('Failed to upload to ftp: '+ str(e))

118
repr (e) daje ci wyjątek (i ciąg komunikatu); str (e) daje tylko ciąg komunikatu.
— białobrody

11
logger.exception(e)Zamiast tego można użyć wyjątku dla rejestrowania wyjątku . Rejestruje wyjątek za pomocą traceback na tym samym logging.ERRORpoziomie.
— mbdevpl,

1
@mbdevpl to nie wydaje się prawdą. Wygląda na to, że wywołuje str () z wyjątkiem: ideone.com/OaCOpO
— KevinOrr

6
except Exception, e:zgłasza mi błąd składniowy w Pythonie 3. Czy jest to oczekiwane?
— Charlie Parker,

27
@CharlieParker w piśmie Python3except Exception as e:
— eumiro

281

Składnia nie jest już obsługiwana w Pythonie 3. Zamiast tego użyj następujących.

try:
    do_something()
except BaseException as e:
    logger.error('Failed to do something: ' + str(e))

2
Właściwie powinieneś użyć logger.error ('Coś nie udało się zrobić:% s', str (e)) W ten sposób, jeśli twój poziom rejestratora jest powyżej błędu, nie interpoluje łańcucha.
— avyfain

7
@avyfain - Jesteś w błędzie. Instrukcja logging.error('foo %s', str(e))zawsze będzie konwertowana ena ciąg. Aby osiągnąć to, czego oczekujesz, użyłbyś logging.error('foo %s', e)- pozwalając w ten sposób ramce rejestrowania wykonać (lub nie) konwersję.
— Ron Dahlgren,

1
Możesz sprawdzić w REPL Pythona (tutaj z Pythonem 3.5.2 i ipython): zobacz moją treść tutaj
— Ron Dahlgren

2
logger.exception(e)Zamiast tego można użyć wyjątku dla rejestrowania wyjątku . Rejestruje wyjątek za pomocą traceback na tym samym logging.ERRORpoziomie.
— mbdevpl,

11
Uważaj na to except BaseExceptioni except Exceptionnie są na tym samym poziomie. except Exceptiondziała w Pythonie 3, ale KeyboardInterruptna przykład nie wyłapuje (co może być bardzo wygodne, jeśli chcesz mieć możliwość przerwania kodu!), ale BaseExceptionprzechwytuje każdy wyjątek. Zobacz ten link, aby uzyskać hierarchię wyjątków.
— jeannej

41

Aktualizacja tego do czegoś prostszego dla programu rejestrującego (działa zarówno dla Pythona 2, jak i 3). Nie potrzebujesz modułu śledzenia.

import logging

logger = logging.Logger('catch_all')

def catchEverythingInLog():
    try:
        ... do something ...
    except Exception as e:
        logger.error(e, exc_info=True)
        ... exception handling ...

To jest teraz stary sposób (choć nadal działa):

import sys, traceback

def catchEverything():
    try:
        ... some operation(s) ...
    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        ... exception handling ...

exc_value to komunikat o błędzie.


2
To byłaby moja preferowana metoda. Wydaje mi się, że po prostu wydrukowanie ciągu jest przydatne do logowania, ale jeśli muszę coś zrobić z tymi informacjami, potrzebuję czegoś więcej niż tylko łańcucha.
— sulimmesh

3
Nie musisz „importować śledzenia” w drugim przykładzie, prawda?
— starikoff,

35

W niektórych przypadkach można użyć e.message lub e.messages .. Ale to nie działa we wszystkich przypadkach. W każdym razie bardziej bezpieczne jest użycie str (e)

try:
  ...
except Exception as e:
  print(e.message)

42
Problem z tym jest, na przykład, jeśli except Exception as ei eto IOError, można uzyskać e.errno, e.filenamei e.strerror, ale najwyraźniej nie ma e.message(przynajmniej w Pythonie 2.7.12). Jeśli chcesz uchwycić komunikat o błędzie, użyj str(e), jak w innych odpowiedziach.
— epalm

@epalm Co się stanie, jeśli złapiesz IOError przed wyjątkiem?
— Albert Thompson

@ HeribertoJuárez Po co łapać specjalne przypadki, podczas gdy możesz po prostu rzucić je na sznurek?
— HosseyNJF

25

Jeśli chcesz mieć klasę błędu, komunikat o błędzie i dane śledzenia stosu (lub niektóre z nich), użyj sys.exec_info().

Minimalny działający kod z pewnym formatowaniem:

import sys
import traceback

try:
    ans = 1/0
except BaseException as ex:
    # Get current system exception
    ex_type, ex_value, ex_traceback = sys.exc_info()

    # Extract unformatter stack traces as tuples
    trace_back = traceback.extract_tb(ex_traceback)

    # Format stacktrace
    stack_trace = list()

    for trace in trace_back:
        stack_trace.append("File : %s , Line : %d, Func.Name : %s, Message : %s" % (trace[0], trace[1], trace[2], trace[3]))

    print("Exception type : %s " % ex_type.__name__)
    print("Exception message : %s" %ex_value)
    print("Stack trace : %s" %stack_trace)

Co daje następujące dane wyjściowe:

Exception type : ZeroDivisionError
Exception message : division by zero
Stack trace : ['File : .\\test.py , Line : 5, Func.Name : <module>, Message : ans = 1/0']

Funkcja sys.exc_info () podaje szczegółowe informacje na temat ostatniego wyjątku. Zwraca krotkę (type, value, traceback).

tracebackjest instancją obiektu traceback. Możesz sformatować ślad za pomocą podanych metod. Więcej można znaleźć w dokumentacji śledzenia .


3
Użycie e.__class__.__name__ może również zwrócić klasę wyjątków.
— kenorb

19

Możesz użyć logger.exception("msg")do rejestrowania wyjątku z funkcją śledzenia:

try:
    #your code
except Exception as e:
    logger.exception('Failed: ' + str(e))

Przypadkowo e.msgjest ciągiem reprezentującym Exceptionklasę.
— MarkHu

5
Lub po prostu logger.exception(e).
— mbdevpl,


5

Możesz spróbować jawnie określić typ wyjątku BaseException. Będzie to jednak wychwytywać tylko pochodne wyjątku BaseException. Chociaż obejmuje to wszystkie wyjątki dostarczone w ramach implementacji, możliwe jest również podniesienie dowolnych klas starego stylu.

try:
  do_something()
except BaseException, e:
  logger.error('Failed to do something: ' + str(e))


2

dla przyszłych walczących, w Pythonie 3.8.2 (i może kilka wcześniejszych wersjach), składnia jest następująca

except Attribute as e:
    print(e)

1

Używając str(e)lub repr(e)do reprezentowania wyjątku, nie otrzymasz rzeczywistego śladu stosu, więc nie jest pomocne ustalenie, gdzie jest wyjątek.

Po przeczytaniu innych odpowiedzi i dokumentacji pakietu rejestrowania, następujące dwa sposoby świetnie sprawdzają się, aby wydrukować rzeczywiste dane śledzenia stosu w celu łatwiejszego debugowania:

użyj logger.debug()z parametremexc_info

try:
    # my code
exception SomeError as e:
    logger.debug(e, exc_info=True)

posługiwać się logger.exception()

lub możemy bezpośrednio użyć logger.exception()do wydrukowania wyjątku.

try:
    # my code
exception SomeError as e:
    logger.exception(e)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.