Error hanyalah nilai yang bersikap buruk
Saat ada yang salah di Python, misalnya membagi dengan nol, membaca file yang tidak ada, atau mengurai angka yang salah, runtime membuat sebuah objek exception lalu mulai membongkar call stack sampai ada yang menangkapnya. Kalau tidak ada yang menangkap, programmu berhenti dan mencetak traceback.
Exception sendiri bukan hal buruk. Exception adalah cara Python memberi tanda "aku tidak bisa melanjutkan operasi ini; ini alasannya." Tugasmu adalah memutuskan, kasus demi kasus, exception mana yang kamu tahu cara memulihkannya dan mana yang sebaiknya dibiarkan naik.
Bentuk dasarnya
try:membuka blok kode yang berisiko.except ValueError:menangkap exception tertentu itu kalau dimunculkan di dalamtry.- Kalau tidak ada exception,
exceptdilewati sepenuhnya.
Jalankan potongan kode itu dengan 42: berhasil. Jalankan dengan hello: handler-nya yang berjalan.
Menangkap exception tertentu
Python punya hierarki tipe exception. Beberapa yang akan sering kamu temui:
ValueError: ada nilai yang salah dalam suatu hal (int("abc"), argumen di luar rentang).TypeError: tipe yang dipakai salah ("hi" + 3).KeyError: key dict tidak ditemukan.IndexError: indeks deretan di luar rentang.FileNotFoundError: sebuah file tidak ada.ZeroDivisionError: mencoba membagi dengan nol.AttributeError: sebuah objek tidak punya atribut yang diminta.
Tangkap exception tertentu yang kamu tahu cara menanganinya:
Kamu bisa menangkap beberapa exception dalam satu klausa dengan memberikan tuple:
Perhatikan as e. Itu mengikat objek exception ke e sehingga kamu bisa memeriksa pesan atau atributnya.
Hindari menangkap semuanya
except: tanpa tipe menangkap benar-benar apa saja, termasuk KeyboardInterrupt (Ctrl-C milikmu) dan perintah keluar di level sistem. Jangan pakai.
except Exception: sedikit lebih baik, tapi tetap berbahaya: ia menelan bug yang tidak kamu duga dan menyembunyikan sumber masalah yang sebenarnya:
# Don't do this without a really good reason.
try:
do_something()
except Exception:
pass
Langkah yang tepat hampir selalu menangkap exception tertentu yang kamu tahu cara memulihkannya. Kalau exception yang tidak terduga sampai ke puncak programmu, traceback akan memberi tahu persis apa yang salah, dan itu fitur, bukan bug.
else dan finally
Pernyataan try punya dua klausa opsional lagi:
elseberjalan kalau bloktryselesai tanpa memunculkan exception.finallyberjalan apa pun yang terjadi, ada exception atau tidak.
else adalah tempat paling rapi untuk kode "hanya saat berhasil": kamu tidak ingin blok try melakukan lebih dari bagian yang memang bisa gagal. finally untuk pembersihan yang harus tetap berjalan walaupun try gagal: menutup resource, melepas lock, mengembalikan state.
Memunculkan exception sendiri
Pakai raise untuk memberi tanda error di kodemu sendiri:
Pilih tipe exception yang sesuai dengan apa yang salah. Pakai dulu yang bawaan, seperti ValueError, TypeError, FileNotFoundError, sebelum mendefinisikan class sendiri.
Mendefinisikan exception sendiri
Kalau yang bawaan tidak bisa menangkap maknanya, definisikan exception khusus:
Wariskan dari Exception (atau tipe bawaan yang lebih spesifik) dan beri class itu sebuah docstring. Biasanya hanya itu yang kamu butuhkan. Exception khusus membuat pemanggil bisa menangkap hanya error yang bermakna bagi domain mereka.
raise ... from ...: exception berantai
Saat satu exception memicu exception lain, pertahankan rantainya:
from e menempelkan error aslinya. Saat traceback dicetak, Python menampilkan keduanya: ConfigError yang muncul dan FileNotFoundError yang menyebabkannya. Jejak seperti itu sangat berharga saat debugging.
Context manager: cara membersihkan yang lebih rapi
finally tidak masalah, tapi untuk resource seperti file, context manager (yang dipakai with) hampir selalu lebih baik:
# finally version
f = open("data.txt")
try:
data = f.read()
finally:
f.close()
# with version
with open("data.txt") as f:
data = f.read()
Keduanya aman. Bentuk with lebih singkat dan berlaku otomatis. Pakai finally hanya kalau kamu melakukan sesuatu yang belum dibungkus standard library dalam sebuah context manager.
Kapan tidak menangkap
Menangkap exception adalah sebuah keputusan: kamu sedang bilang "aku bisa menangani ini." Kalau tidak bisa, biarkan exception itu merambat. Kode seperti ini hampir selalu keliru:
try:
do_work()
except Exception:
pass # silently ignore everything
Membungkam error membuat bug tidak terlihat. Lebih baik program crash dengan jelas daripada terus berjalan tertatih-tatih dalam keadaan yang tidak konsisten.
Rangkuman
try/exceptmemungkinkan kamu menangani error yang bisa dipulihkan.- Tangkap exception tertentu, bukan
Exceptionsecara membabi buta. raisememberi tanda error di kodemu sendiri.- Blok
withmenggantikan sebagian besar pembersihan denganfinally. - Kalau ragu, biarkan exception-nya merambat.
Berikutnya: tur error spesifik yang paling sering dimunculkan Python, seperti KeyError, ValueError, ModuleNotFoundError, dan beberapa lainnya, beserta kebiasaan debugging yang memperbaikinya dengan cepat.
Pertanyaan yang sering diajukan
Bagaimana cara menangani error di Python?
Bungkus kode yang berisiko dalam blok try dan tangkap exception tertentu dalam blok except: try: risky() except ValueError: .... else yang opsional berjalan kalau tidak ada exception; finally berjalan apa pun yang terjadi, untuk pembersihan.
Apakah sebaiknya aku menangkap Exception agar aman?
Tidak. except: tanpa tipe atau except Exception: menyembunyikan bug yang tidak kamu duga. Tangkap exception tertentu yang kamu tahu cara memulihkannya, dan biarkan sisanya merambat agar kamu melihat masalah yang sebenarnya.
Apa bedanya raise dan raise from?
raise NewError(...) memunculkan exception baru. raise NewError(...) from original tetap menempelkan exception aslinya sebagai penyebab, yang ditampilkan Python di traceback. Pakai from saat error di level bawah memicu error di level atas yang ingin kamu tampilkan.