menangkap pesan pengecualian python

521
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))

Ini sepertinya tidak berhasil, saya mendapatkan kesalahan sintaksis, apa cara yang tepat untuk melakukan ini untuk masuk semua jenis pengecualian ke file

Hellnar
sumber
2
Lekukan Anda rusak. Dan hilangkan ,setelahnya except.
Sven Marnach
3
@VenMarnach, jika Anda menghilangkan ,setelah except, Anda akan mendapatkan global name 'e' is not defined, yang tidak jauh lebih baik daripada sintaks yang salah.
Val
12
@Val: Seharusnya except Exception as eatau except Exception, e, tergantung pada versi Python.
Sven Marnach
1
Mungkin ada di sekitar 8 jawaban itu, tetapi ketika Anda membuka file, bagian dekat tidak boleh berada di dalam pernyataan coba, tetapi baik dalam pernyataan akhirnya atau dibungkus dengan pernyataan with.
JC Rocamonde

Jawaban:

733

Anda harus menentukan jenis pengecualian yang ingin Anda tangkap. Jadi tulis except Exception, e:alih-alih except, e:untuk pengecualian umum (yang akan tetap dicatat).

Kemungkinan lain adalah menulis seluruh percobaan Anda / kecuali kode dengan cara ini:

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))

dalam Python 3.x dan versi modern dari Python 2.x digunakan except Exception as esebagai ganti 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))
eumiro
sumber
118
repr (e) memberi Anda pengecualian (dan string pesan); str (e) hanya memberikan string pesan.
whitebeard
11
Sebagai alternatif untuk pengecualian logging, Anda dapat menggunakannya logger.exception(e). Ini akan mencatat pengecualian dengan traceback pada logging.ERRORlevel yang sama .
mbdevpl
1
@ mbdevpl ini sepertinya tidak benar. Tampaknya untuk memanggil str () pada pengecualian: ideone.com/OaCOpO
KevinOrr
6
except Exception, e:melempar kesalahan Sintaks kepada saya di python 3. Apakah ini diharapkan?
Charlie Parker
27
@CharlieParker dalam Python3 writeexcept Exception as e:
eumiro
282

Sintaks tidak lagi didukung dalam python 3. Gunakan yang berikut sebagai gantinya.

try:
    do_something()
except BaseException as e:
    logger.error('Failed to do something: ' + str(e))
sjtaheri
sumber
2
Sebenarnya, Anda harus menggunakan logger.error ('Gagal melakukan sesuatu:% s', str (e)) Dengan cara itu, jika tingkat logger Anda di atas kesalahan itu tidak melakukan interpolasi string.
avyfain
7
@avyfain - Anda salah. Pernyataan logging.error('foo %s', str(e))akan selalu dikonversi eke string. Untuk mencapai apa yang Anda inginkan, Anda akan menggunakan logging.error('foo %s', e)- dengan demikian memungkinkan kerangka logging untuk melakukan (atau tidak melakukan) konversi.
Ron Dahlgren
1
Anda dapat memverifikasi dengan python REPL (di sini dengan Python 3.5.2 dan ipython): lihat inti saya di sini
Ron Dahlgren
2
Sebagai alternatif untuk pengecualian logging, Anda dapat menggunakannya logger.exception(e). Ini akan mencatat pengecualian dengan traceback pada logging.ERRORlevel yang sama .
mbdevpl
11
Waspadalah except BaseExceptiondan except Exceptiontidak berada pada level yang sama. except Exceptiontidak bekerja di Python3, tetapi tidak akan menangkap KeyboardInterruptmisalnya (yang bisa sangat nyaman jika Anda ingin dapat mengganggu kode Anda!), sedangkan BaseExceptionmenangkap pengecualian apa pun. Lihat tautan ini untuk hierarki pengecualian.
jeannej
41

Memperbarui ini menjadi sesuatu yang lebih sederhana untuk logger (berfungsi untuk python 2 dan 3). Anda tidak perlu modul traceback.

import logging

logger = logging.Logger('catch_all')

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

Ini sekarang cara lama (meskipun masih berfungsi):

import sys, traceback

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

exc_value adalah pesan kesalahan.

berniey
sumber
2
Ini akan menjadi metode pilihan saya. Hanya mencetak string berguna untuk logging, saya kira, tetapi jika saya perlu melakukan sesuatu dengan informasi itu saya membutuhkan lebih dari sekedar string.
sulimmesh
3
Anda tidak perlu 'mengimpor traceback' pada contoh kedua, bukan?
starikoff
34

Ada beberapa kasus di mana Anda dapat menggunakan e.message atau e.messages .. Tetapi tidak berfungsi dalam semua kasus. Pokoknya yang lebih aman adalah dengan menggunakan str (e)

try:
  ...
except Exception as e:
  print(e.message)
Slipstream
sumber
42
Masalah dengan hal ini adalah, misalnya, jika Anda except Exception as e, dan emerupakan IOError, Anda mendapatkan e.errno, e.filenamedan e.strerror, tapi tampaknya tidak ada e.message(setidaknya di Python 2.7.12). Jika Anda ingin menangkap pesan kesalahan, gunakan str(e), seperti pada jawaban lainnya.
epalm
@epalm Bagaimana jika Anda menangkap IOError sebelum Exception?
Albert Thompson
@ HeribertoJuárez Mengapa menangkap kasing khusus sementara Anda bisa melemparkannya ke string?
HosseyNJF
25

Jika Anda ingin kelas kesalahan, pesan kesalahan dan jejak stack (atau beberapa di antaranya), gunakan sys.exec_info().

Kode kerja minimal dengan beberapa format:

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)

Yang menghasilkan output sebagai berikut:

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

Fungsi sys.exc_info () memberi Anda detail tentang pengecualian terbaru. Ini mengembalikan tuple dari (type, value, traceback).

tracebackadalah turunan dari objek traceback. Anda dapat memformat jejak dengan metode yang disediakan. Lebih banyak dapat ditemukan dalam dokumentasi traceback .

Kavindu Dodanduwa
sumber
3
Menggunakan e.__class__.__name__ dapat mengembalikan kelas pengecualian juga.
kenorb
19

Anda dapat menggunakan logger.exception("msg")untuk mencatat pengecualian dengan traceback:

try:
    #your code
except Exception as e:
    logger.exception('Failed: ' + str(e))
Peter
sumber
Secara kebetulan, e.msgadalah representasi string dari Exceptionkelas.
MarkHu
5
Atau sederhananya logger.exception(e).
mbdevpl
5

Anda dapat mencoba menentukan jenis BaseException secara eksplisit. Namun, ini hanya akan menangkap turunan dari BaseException. Meskipun ini mencakup semua pengecualian yang disediakan implementasi, juga dimungkinkan untuk meningkatkan kelas gaya lama yang sewenang-wenang.

try:
  do_something()
except BaseException, e:
  logger.error('Failed to do something: ' + str(e))
Heini Høgnason
sumber
4

Gunakan str (ex) untuk mencetak eksekusi

try:
   #your code
except ex:
   print(str(ex))
Niraj Trivedi
sumber
2

untuk pejuang masa depan, dalam python 3.8.2 (dan mungkin beberapa versi sebelum itu), sintaksnya adalah

except Attribute as e:
    print(e)
syter
sumber
1

Menggunakan str(e)atau repr(e)untuk mewakili pengecualian, Anda tidak akan mendapatkan jejak tumpukan yang sebenarnya, sehingga tidak membantu untuk menemukan di mana pengecualian itu.

Setelah membaca jawaban lain dan dokumen paket logging, dua cara berikut berfungsi dengan baik untuk mencetak jejak stack yang sebenarnya untuk memudahkan debugging:

gunakan logger.debug()dengan parameterexc_info

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

menggunakan logger.exception()

atau bisa langsung kita gunakan logger.exception()untuk mencetak pengecualian.

try:
    # my code
exception SomeError as e:
    logger.exception(e)
jdhao
sumber