Saat menggunakan PyCharm IDE, penggunaan except:
tanpa jenis pengecualian memicu pengingat dari IDE bahwa klausa pengecualian ini adalah Too broad
.
Haruskah saya mengabaikan nasihat ini? Atau apakah Pythonic selalu menentukan jenis pengecualian?
Saat menggunakan PyCharm IDE, penggunaan except:
tanpa jenis pengecualian memicu pengingat dari IDE bahwa klausa pengecualian ini adalah Too broad
.
Haruskah saya mengabaikan nasihat ini? Atau apakah Pythonic selalu menentukan jenis pengecualian?
Jawaban:
Hampir selalu lebih baik untuk menentukan jenis pengecualian eksplisit. Jika Anda menggunakan except:
klausa telanjang , Anda mungkin akan menemukan pengecualian selain yang Anda harapkan untuk ditangkap - ini dapat menyembunyikan bug atau mempersulit program debug ketika mereka tidak melakukan apa yang Anda harapkan.
Misalnya, jika Anda menyisipkan baris ke dalam database, Anda mungkin ingin menangkap pengecualian yang menunjukkan bahwa baris tersebut sudah ada, sehingga Anda bisa melakukan pembaruan.
try:
insert(connection, data)
except:
update(connection, data)
Jika Anda menentukan telanjang except:
, Anda juga akan menemukan kesalahan soket yang menunjukkan bahwa server database telah jatuh. Sebaiknya hanya menangkap pengecualian yang Anda tahu cara menanganinya - seringkali lebih baik jika program gagal pada titik pengecualian daripada melanjutkan tetapi berperilaku aneh dan tidak terduga.
Satu kasus di mana Anda mungkin ingin menggunakan telanjang except:
adalah di tingkat atas program yang Anda butuhkan untuk selalu berjalan, seperti server jaringan. Tapi kemudian, Anda harus sangat berhati-hati untuk mencatat pengecualian, jika tidak, tidak mungkin mengetahui apa yang salah. Pada dasarnya, hanya boleh ada paling banyak satu tempat dalam program yang melakukan ini.
Konsekuensi dari semua ini adalah bahwa kode Anda tidak boleh melakukannya raise Exception('some message')
karena memaksa kode klien untuk digunakan except:
(atau except Exception:
yang hampir sama buruknya). Anda harus menentukan pengecualian khusus untuk masalah yang ingin Anda beri sinyal (mungkin mewarisi dari beberapa subkelas pengecualian bawaan seperti ValueError
atau TypeError
). Atau Anda harus meningkatkan pengecualian bawaan tertentu. Ini memungkinkan pengguna kode Anda untuk berhati-hati dalam menangkap hanya pengecualian yang ingin mereka tangani.
except:
juga menangkap (di antara banyak hal lainnya) NameError
dan AttributeError
, jadi jika Anda salah mengeja sesuatu di try
blok (misalnya fungsi "sisipkan" Anda sebenarnya dipanggil insert_one
karena seseorang tidak menghargai konsistensi sebanyak yang seharusnya), itu selalu diam-diam mencoba update()
.
main()
)?
except Exception:
akan menangkap NameError
dan AttributeError
juga. Apa yang membuat telanjang except:
begitu buruk adalah bahwa ia menangkap hal-hal yang tidak ada urusannya ditangkap, misalnya SystemExit
(diangkat saat Anda menelepon exit
atau sys.exit
, dan sekarang Anda telah mencegah jalan keluar yang diinginkan) dan KeyboardInterrupt
(sekali lagi, jika pengguna memukul Ctrl-C
, Anda mungkin tidak ingin untuk tetap berlari hanya untuk membencinya). Hanya yang terakhir yang masuk akal untuk ditangkap, dan itu harus ditangkap secara eksplisit. Setidaknya except Exception:
biarkan keduanya menyebar secara normal.
Anda tidak boleh mengabaikan nasihat yang diberikan penerjemah kepada Anda.
Dari Panduan Gaya PEP-8 untuk Python:
Saat menangkap pengecualian, sebutkan pengecualian khusus bila memungkinkan daripada menggunakan klausa kecuali: telanjang.
Misalnya, gunakan:
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
A bare exception: clause akan menangkap pengecualian SystemExit dan KeyboardInterrupt, membuatnya lebih sulit untuk mengganggu program dengan Control-C, dan dapat menyamarkan masalah lain. Jika Anda ingin menangkap semua pengecualian yang menandakan kesalahan program, gunakan kecuali Exception: (telanjang kecuali sama dengan kecuali BaseException :).
Aturan praktis yang baik adalah membatasi penggunaan klausa 'kecuali' untuk dua kasus:
Jika penangan pengecualian akan mencetak atau mencatat traceback; setidaknya pengguna akan menyadari bahwa telah terjadi kesalahan. Jika kode perlu melakukan beberapa pekerjaan pembersihan, tetapi kemudian biarkan pengecualian menyebar ke atas dengan kenaikan. coba ... akhirnya bisa menjadi cara yang lebih baik untuk menangani kasus ini.
Ini tidak spesifik untuk Python.
Inti dari pengecualian adalah menangani masalah sedekat mungkin dengan penyebabnya.
Jadi, Anda menyimpan kode yang dapat dalam keadaan luar biasa dapat memicu masalah dan resolusi "bersebelahan" satu sama lain.
Masalahnya adalah Anda tidak bisa mengetahui semua pengecualian yang bisa dilemparkan oleh sepotong kode. Yang dapat Anda ketahui adalah bahwa jika itu adalah pengecualian untuk mengatakan file tidak ditemukan, maka Anda bisa menjebaknya dan meminta pengguna untuk mendapatkan yang tidak atau membatalkan fungsi.
Jika Anda mencoba menangkapnya, maka tidak peduli masalah apa yang ada dalam rutin file Anda (hanya baca, izin, UAC, bukan pdf, dll), setiap orang akan masuk ke file Anda tidak ditemukan, dan pengguna Anda berteriak "tapi itu ada, kode ini omong kosong"
Sekarang ada beberapa situasi di mana Anda mungkin menangkap semuanya, tetapi mereka harus dipilih secara sadar.
Mereka menangkap, membatalkan beberapa tindakan lokal (seperti membuat atau mengunci sumber daya, (membuka file pada disk untuk menulis misalnya), lalu Anda melempar pengecualian lagi, untuk ditangani di tingkat yang lebih tinggi)
Anda yang lain adalah Anda tidak peduli mengapa itu salah. Mencetak misalnya. Anda mungkin memiliki pemahaman bahwa, untuk mengatakan Ada beberapa masalah dengan printer Anda, tolong selesaikan, dan jangan mematikan aplikasi karena itu. Ona sama sia-sia jika kode Anda mengeksekusi serangkaian tugas terpisah menggunakan semacam jadwal, Anda tidak ingin semuanya mati, karena salah satu tugas gagal.
Catatan Jika Anda melakukan hal di atas, saya tidak dapat merekomendasikan semacam pencatatan pengecualian, misalnya coba tangkap log akhir, cukup tinggi.
Anda juga akan menangkap misalnya Control-C dengan itu, jadi jangan lakukan kecuali Anda "membuang" lagi. Namun, dalam hal ini Anda sebaiknya menggunakan "akhirnya".
Selalu menentukan jenis pengecualian, ada banyak jenis Anda tidak ingin menangkap, seperti SyntaxError
, KeyboardInterrupt
, MemoryError
dll
except Exception:
menghindari jenis di atas yang tidak ingin kita tangkap?
except Exception
baik-baik saja.
except Exception
menangkap SyntaxError
dan MemoryError
karena itu adalah kelas dasar mereka. KeyboardInterrupt
, SystemExit
(dimunculkan oleh sys.exit()
) tidak tertangkap (mereka adalah subclass BaseException langsung)
Berikut adalah tempat-tempat yang saya gunakan kecuali tanpa tipe
Itulah penggunaan utama dalam kode saya untuk pengecualian yang tidak dicentang
Saya selalu menambahkan ini, sehingga kode produksi tidak menumpahkan stacktraces
Saya punya dua cara untuk melakukannya:
Saya lebih suka dengan cara ini, saya merasa lebih mudah untuk mendeteksi pengecualian mana yang seharusnya ditangkap dengan tepat: saya "melihat" masalah dengan lebih baik ketika pengecualian tingkat yang lebih rendah dicatat oleh tingkat yang lebih tinggi
Beberapa rekan kerja lebih suka cara ini, karena cara ini mempertahankan pengecualian tingkat yang lebih rendah di fungsi tingkat yang lebih rendah, di mana mereka "termasuk".