Seperti benar Anda menebak, ada dua sisi untuk itu: Penangkapan setiap kesalahan dengan menetapkan tidak ada jenis terkecuali setelah except
, dan hanya lewat itu tanpa mengambil tindakan apapun.
Penjelasan saya adalah "sedikit" lebih lama — jadi t; dr itu dipecah menjadi ini:
- Jangan sampai ada kesalahan . Selalu tentukan pengecualian mana yang Anda siap untuk pulihkan dan hanya menangkapnya.
- Cobalah untuk menghindari lewat kecuali blok . Kecuali diinginkan secara eksplisit, ini biasanya bukan pertanda baik.
Tapi mari kita masuk ke detail:
Jangan sampai ada kesalahan
Saat menggunakan try
blok, Anda biasanya melakukan ini karena Anda tahu bahwa ada kemungkinan pengecualian dilemparkan. Dengan demikian, Anda juga sudah memiliki perkiraan tentang apa yang bisa dipatahkan dan pengecualian apa yang bisa dilemparkan. Dalam kasus seperti itu, Anda menangkap pengecualian karena Anda dapat memulihkannya secara positif . Itu berarti bahwa Anda siap untuk pengecualian dan memiliki beberapa rencana alternatif yang akan Anda ikuti jika pengecualian itu.
Misalnya, ketika Anda meminta pengguna untuk memasukkan nomor, Anda dapat mengonversi input yang menggunakan int()
yang dapat meningkatkan a ValueError
. Anda dapat dengan mudah memulihkannya dengan hanya meminta pengguna untuk mencobanya lagi, jadi menangkap ValueError
dan mendorong pengguna lagi akan menjadi rencana yang tepat. Contoh lain adalah jika Anda ingin membaca beberapa konfigurasi dari file, dan file itu kebetulan tidak ada. Karena ini adalah file konfigurasi, Anda mungkin memiliki beberapa konfigurasi default sebagai cadangan, sehingga file tersebut tidak benar-benar diperlukan. Jadi menangkap FileNotFoundError
dan hanya menerapkan konfigurasi default akan menjadi rencana yang bagus di sini. Sekarang dalam kedua kasus ini, kami memiliki pengecualian yang sangat spesifik yang kami harapkan dan memiliki rencana yang sama spesifik untuk pulih darinya. Dengan demikian, dalam setiap kasus, kami hanya secara eksplisit except
tertentu pengecualian.
Namun, jika kita ingin menangkap semuanya , maka — selain pengecualian-pengecualian itu kita siap untuk pulih dari — ada juga kemungkinan bahwa kita mendapatkan pengecualian yang tidak kita harapkan, dan yang memang tidak bisa kita pulihkan dari; atau tidak seharusnya pulih dari.
Mari kita ambil contoh file konfigurasi dari atas. Seandainya ada file yang hilang, kami hanya menerapkan konfigurasi default kami, dan mungkin memutuskan di lain waktu untuk secara otomatis menyimpan konfigurasi (jadi lain kali, file itu ada). Sekarang bayangkan kita mendapat IsADirectoryError
, atau aPermissionError
sebagai gantinya. Dalam kasus seperti itu, kami mungkin tidak ingin melanjutkan; kami masih bisa menerapkan konfigurasi default kami, tetapi kami nanti tidak akan dapat menyimpan file. Dan sepertinya pengguna juga memiliki konfigurasi khusus, jadi menggunakan nilai default kemungkinan tidak diinginkan. Jadi kami ingin memberi tahu pengguna tentang hal itu segera, dan mungkin membatalkan eksekusi program juga. Tapi itu bukan sesuatu yang ingin kita lakukan di suatu tempat jauh di dalam beberapa bagian kode kecil; ini adalah sesuatu yang penting di level aplikasi, jadi itu harus ditangani di atas — jadi biarkan pengecualian muncul.
Contoh sederhana lain juga disebutkan dalam dokumen idiom Python 2 . Di sini, salah ketik sederhana ada dalam kode yang menyebabkannya rusak. Karena kami menangkap setiap pengecualian, kami juga menangkap NameError
s dan SyntaxError
s . Keduanya adalah kesalahan yang terjadi pada kita semua saat pemrograman; dan keduanya adalah kesalahan yang sama sekali tidak ingin kami sertakan saat mengirimkan kode. Tetapi karena kami juga menangkapnya, kami bahkan tidak tahu bahwa itu terjadi di sana dan kehilangan bantuan untuk men-debug dengan benar.
Tetapi ada juga pengecualian yang lebih berbahaya yang tidak mungkin kita siapkan. Misalnya SystemError biasanya sesuatu yang jarang terjadi dan yang tidak bisa kita rencanakan; itu berarti ada sesuatu yang lebih rumit sedang terjadi, sesuatu yang kemungkinan mencegah kita melanjutkan tugas saat ini.
Bagaimanapun, sangat tidak mungkin bahwa Anda siap untuk semuanya dalam bagian skala kecil dari kode, jadi di situlah Anda hanya perlu menangkap pengecualian yang telah Anda siapkan. Beberapa orang menyarankan untuk menangkap setidaknya Exception
karena tidak akan mencakup hal-hal seperti SystemExit
dan KeyboardInterrupt
yang dengan desain untuk menghentikan aplikasi Anda, tetapi saya berpendapat bahwa ini masih terlalu spesifik. Hanya ada satu tempat di mana saya secara pribadi menerima penangkapan Exception
atau sembarang tempatpengecualian, dan itu ada dalam penangan pengecualian tingkat aplikasi global tunggal yang memiliki tujuan tunggal untuk mencatat pengecualian apa pun yang tidak kami persiapkan. Dengan begitu, kita masih dapat menyimpan sebanyak mungkin informasi tentang pengecualian yang tidak terduga, yang kemudian dapat kita gunakan untuk memperluas kode kita untuk menangani kode-kode itu secara eksplisit (jika kita dapat memulihkannya) atau — jika ada bug — untuk membuat kasus uji untuk memastikan itu tidak akan terjadi lagi. Tapi tentu saja, itu hanya berfungsi jika kita hanya menangkap pengecualian yang sudah kita harapkan, jadi yang tidak kita harapkan akan muncul secara alami.
Cobalah untuk menghindari lewat kecuali blok
Ketika secara eksplisit menangkap sejumlah kecil pengecualian khusus, ada banyak situasi di mana kita akan baik-baik saja dengan tidak melakukan apa-apa. Dalam kasus seperti itu, memiliki except SomeSpecificException: pass
saja tidak apa-apa Namun, sebagian besar waktu, ini tidak terjadi karena kita mungkin memerlukan beberapa kode yang berkaitan dengan proses pemulihan (seperti yang disebutkan di atas). Ini bisa berupa sesuatu yang mencoba lagi tindakan, atau untuk menetapkan nilai default sebagai gantinya.
Jika bukan itu masalahnya, misalnya karena kode kami sudah terstruktur untuk diulangi sampai berhasil, maka hanya lewat saja sudah cukup. Mengambil contoh kami dari atas, kami mungkin ingin meminta pengguna untuk memasukkan nomor. Karena kami tahu bahwa pengguna ingin tidak melakukan apa yang kami minta, kami mungkin hanya memasukkannya ke dalam lingkaran, sehingga bisa terlihat seperti ini:
def askForNumber ():
while True:
try:
return int(input('Please enter a number: '))
except ValueError:
pass
Karena kami terus berusaha sampai tidak ada pengecualian yang dilemparkan, kami tidak perlu melakukan sesuatu yang istimewa di blok kecuali, jadi ini baik-baik saja. Tapi tentu saja, orang mungkin berargumen bahwa kami setidaknya ingin menunjukkan kepada pengguna beberapa pesan kesalahan untuk memberi tahu mengapa ia harus mengulangi input.
Namun dalam banyak kasus lain, hanya lewat dalam except
adalah tanda bahwa kita tidak benar-benar siap untuk pengecualian yang kita tangkap. Kecuali jika pengecualian itu sederhana (suka ValueError
atau tidak TypeError
), dan alasan mengapa kita bisa lulus sudah jelas, cobalah untuk tidak hanya lewat. Jika benar-benar tidak ada yang dapat dilakukan (dan Anda benar-benar yakin tentang hal itu), maka pertimbangkan untuk menambahkan komentar mengapa demikian; jika tidak, perluas blok kecuali untuk benar-benar memasukkan beberapa kode pemulihan.
except: pass
Pelaku terburuk adalah kombinasi keduanya. Ini berarti bahwa kita rela menangkap kesalahan apa pun meskipun kita sama sekali tidak siap untuk itu dan kita juga tidak melakukan apa-apa. Anda setidaknya ingin mencatat kesalahan dan juga kemungkinan mengembalikannya untuk tetap menghentikan aplikasi (sepertinya Anda tidak dapat melanjutkan seperti biasa setelah MemoryError). Melewati saja tidak hanya akan membuat aplikasi tetap hidup (tergantung di mana Anda menangkap tentu saja), tetapi juga membuang semua informasi, sehingga tidak mungkin untuk menemukan kesalahan — yang terutama benar jika Anda bukan orang yang menemukannya.
Jadi intinya adalah: Hanya menangkap pengecualian yang benar-benar Anda harapkan dan siap untuk pulih dari; semua yang lain kemungkinan adalah kesalahan yang harus Anda perbaiki, atau sesuatu yang Anda tidak siap untuk melakukannya. Melewati pengecualian spesifik tidak masalah jika Anda benar-benar tidak perlu melakukan sesuatu tentang hal itu. Dalam semua kasus lain, itu hanya tanda anggapan dan malas. Dan Anda pasti ingin memperbaikinya.
logging
modul pada tingkat DEBUG untuk menghindari mereka mengalir keluar dalam produksi, tetapi tetap tersedia dalam pengembangan.