Apa cara terbaik untuk mendapatkan pesan pengecualian dari komponen pustaka standar dengan Python?
Saya perhatikan bahwa dalam beberapa kasus Anda bisa mendapatkannya melalui message
lapangan seperti ini:
try:
pass
except Exception as ex:
print(ex.message)
tetapi dalam beberapa kasus (misalnya, jika terjadi kesalahan soket) Anda harus melakukan sesuatu seperti ini:
try:
pass
except socket.error as ex:
print(ex)
Saya bertanya-tanya apakah ada cara standar untuk mencakup sebagian besar situasi ini?
python
exception
exception-handling
Hati yang beku
sumber
sumber
except Foo as bar:
sama denganexcept Foo, bar:
(kecuali yang pertama lebih baru, dan akan terus berfungsi di 3.x), apakah kesalahan datang denganmessage
atribut atau tidak terpisah..message
kesalahan adalah cara standar atau tidak?print(msg)
hanyalah jalan pintas untukprint(str(msg))
message
sudah usang.Jawaban:
Jika Anda melihat dokumentasi untuk kesalahan bawaan , Anda akan melihat bahwa sebagian besar
Exception
kelas menetapkan argumen pertama mereka sebagaimessage
atribut. Tidak semua dari mereka melakukannya.Khususnya,
EnvironmentError
(dengan subclassIOError
danOSError
) memiliki argumen pertamaerrno
, keduastrerror
. Tidak adamessage
... yangstrerror
secara kasar analog dengan apa yang biasanya menjadimessage
.Secara umum, subkelas dari
Exception
dapat melakukan apapun yang mereka inginkan. Mereka mungkin memiliki atau tidak memilikimessage
atribut. Bawaan masa depanException
mungkin tidak memilikimessage
atribut. SetiapException
subclass yang diimpor dari pustaka pihak ketiga atau kode pengguna mungkin tidak memilikimessage
atribut.Saya pikir cara yang tepat untuk menangani ini adalah dengan mengidentifikasi
Exception
subclass spesifik yang ingin Anda tangkap, dan kemudian hanya menangkap subclass tersebut, bukan semuanya dengan anexcept Exception
, lalu gunakan atribut apa pun yang ditentukan oleh subclass tertentu seperti yang Anda inginkan.Jika Anda memerlukan
print
sesuatu, saya pikir mencetak hasil tangkapanException
itu sendiri kemungkinan besar akan melakukan apa yang Anda inginkan, apakah itu memilikimessage
atribut atau tidak.Anda juga dapat memeriksa atribut pesan jika Anda mau, seperti ini, tetapi saya tidak akan menyarankannya karena tampaknya berantakan:
try: pass except Exception as e: # Just print(e) is cleaner and more likely what you want, # but if you insist on printing message specifically whenever possible... if hasattr(e, 'message'): print(e.message) else: print(e)
sumber
str(ex)
selain hanyaex
?print()
secara otomatis memanggilstr()
Anda. Tidak ada alasan untuk memanggilnya sendiri secara manual, meskipun tidak berbahaya karena memanggilstr()
string hanya akan mengembalikan string itu sendiri.str()
pesan jika jenisnyaunicode
.Untuk meningkatkan jawaban yang diberikan oleh @artofwarfare , inilah yang saya anggap sebagai cara yang lebih rapi untuk memeriksa
message
atribut dan mencetaknya atau mencetakException
objek sebagai cadangan.try: pass except Exception as e: print getattr(e, 'message', repr(e))
Panggilan ke
repr
bersifat opsional, tetapi saya merasa perlu dalam beberapa kasus penggunaan.Perbarui # 1:
Mengikuti komentar @MadPhysicist , berikut adalah bukti mengapa panggilan ke
repr
mungkin diperlukan. Coba jalankan kode berikut di interpreter Anda:try: raise Exception except Exception as e: print(getattr(e, 'message', repr(e))) print(getattr(e, 'message', str(e)))
Perbarui # 2:
Berikut adalah demo dengan spesifikasi untuk Python 2.7 dan 3.5: https://gist.github.com/takwas/3b7a6edddef783f2abddffda1439f533
sumber
getattr
melempar pengecualian jika objek yang diteruskan tidak memiliki atribut yang diminta. Jika Anda ingin melakukan sesuatu seperti itu, saya pikir Anda harus menggunakan argumen ketiga opsional untukgetattr
, seperti ini:print getattr(e, 'message', e)
. Jauh lebih baik dari apa yang saya lakukan. Pilihan lainnya adalahprint(e.message if hasattr(e, 'message') else e)
.str
bukanrepr
.str
,repr
tambahkan saja nama kelas. Alih-alih menggunakanrepr
, saya mengusulkan untuk menggunakanprint('{e.__class__.__name__}: {e}'.format(e=e))
. Hasil cetak lebih bersih dan sesuai dengan hasil cetak kenaikan itu sendiri.'{e.__class__.__module__}.{e.__class__.__name__}: {e}'
repr(e)
untuk saat ini satu-satunya solusi yang membantu saya mencetak setidaknya sejumlah kecil info tentang kesalahan yang saya tangkap dalam beberapa keadaan tertentu.repr(e)
menghasilkanKeyError(0,)
(yang merupakan kesalahan), sementarastr(e)
ataue.message
hanya menghasilkan0
atau tidak sama sekali.Saya memiliki masalah yang sama. Saya pikir solusi terbaik adalah menggunakan log.exception, yang secara otomatis akan mencetak jejak tumpukan dan pesan kesalahan, seperti:
try: pass log.info('Success') except: log.exception('Failed')
sumber
log
? Saya baru saja mencobaimport log
Python 2.7.13 dan mendapat pesan bahwa tidak ada modul dengan nama itu. Apakah itu sesuatu yang Anda tambahkan melaluipip
atau apakah itu ditambahkan dalam versi python yang lebih baru (saya tahu, saya tahu, saya perlu memperbarui ke Python 3 ... Saya akan melakukannya segera setelah CentOS menghentikan pengiriman dengan Python 2 secara default ...)import logging
\ nlog = logging.getLogger(__name__)
Saya juga punya masalah yang sama. Menggali ini saya menemukan bahwa kelas Exception memiliki
args
atribut, yang menangkap argumen yang digunakan untuk membuat pengecualian. Jika Anda mempersempit pengecualian yang akan ditangkap kecuali untuk subset, Anda harus dapat menentukan bagaimana mereka dibangun, dan dengan demikian argumen mana yang berisi pesan tersebut.try: # do something that may raise an AuthException except AuthException as ex: if ex.args[0] == "Authentication Timeout.": # handle timeout else: # generic handling
sumber