Crash total adalah reaksi yang terlalu keras untuk kesalahan kecil. Ketika pengguna mengetik “dua puluh” pada kolom umur, program seharusnya bisa meminta input ulang, bukan mati dengan traceback. Perangkat Python untuk itu adalah pernyataan try dan except. Pada Chapter ini kita akan membedah cara kerja penangkapan exception, mengapa klausa except harus ditulis spesifik, dan bagaimana membaca isi exception yang tertangkap.

Menangkap Exception dengan try dan except #

Pernyataan try membungkus kode yang berisiko gagal. Mekanismenya: interpreter Python menjalankan blok try baris demi baris. Begitu sebuah exception muncul, interpreter Python meninggalkan sisa blok try saat itu juga, lalu mencari klausa except yang cocok dengan class exception tersebut. Jika cocok, blok handler dijalankan dan program lanjut hidup; jika tidak ada, exception diteruskan keluar seperti perilaku default yang kita lihat pada Chapter Memahami Exceptions.

python
umur_text = "dua puluh"

try:
    umur = int(umur_text)
    print("Konversi berhasil:", umur)
except ValueError:
    print("Input bukan angka yang valid")

Output yang Dihasilkan:

text
Input bukan angka yang valid

Mari kita telaah apa yang terjadi pada baris-baris kode di atas:

  1. Baris 3 (try:): interpreter Python mulai menjalankan blok try dengan pengawasan.
  2. Baris 4 (umur = int(umur_text)): function int() gagal mengonversi string "dua puluh" dan membangkitkan ValueError. Baris 5 tidak pernah dieksekusi.
  3. Baris 6 (except ValueError:): interpreter Python mencocokkan class exception dengan klausa ini — cocok, jadi blok handler dijalankan.
  4. Baris 7 (print(...)): pesan cadangan dicetak, lalu eksekusi normal berlanjut ke kode setelah pernyataan try.

Perhatikan bahwa print() pada baris 5 tidak pernah berjalan. Saat exception muncul di tengah blok try, seluruh sisa baris blok tersebut dilewati.

Tangani Exception yang Spesifik #

Klausa except yang menyebut nama class secara eksplisit menjelaskan kegagalan apa yang dipersiapkan program. Contoh berikut menangkap IndexError saat membaca list:

python
peserta = ["Budi", "Siti"]

try:
    print("Peserta ketiga:", peserta[2])
except IndexError:
    print("Nomor peserta tidak ditemukan")

Output yang Dihasilkan:

text
Nomor peserta tidak ditemukan

Handler spesifik memberi dua manfaat. Pertama, niat kode terbaca jelas: blok tersebut hanya bereaksi terhadap kehabisan index. Kedua, bug lain tetap bocor keluar — misalnya TypeError akibat salah tipe — sehingga tetap terlihat saat pengembangan, bukan tertelan diam-diam.

Bahaya bare except #

Klausa except: tanpa nama class, disebut bare except, menangkap semua exception tanpa terkecuali. Perhatikan kasus berikut:

python
def tampilkan_diskon(persentase):
    print(f"Diskon hari ini: {persentase}%")

try:
    tampil_diskon(20)
except:
    print("Terjadi kesalahan")

Output yang Dihasilkan:

text
Terjadi kesalahan

Kode di atas tidak jalan sebagaimana mestinya: nama function tertulis tampil_diskon, padahal definisinya tampilkan_diskon. Kesalahan ketik itu membangkitkan NameError, dan bare except menelan error tersebut seolah-olah itu bagian dari alur normal. Programmer jadi tidak menyadari ada bug.

Ringkasan tiga pola klausa except:

PolaCakupanKapan pantas
except:seluruh BaseException, termasuk Ctrl+C dan SystemExithampir tidak pernah
except Exception:hampir seluruh exception runtimejaring pengaman di lapisan teratas
except ValueError:hanya ValueError (dan sub-class-nya)pilihan utama sehari-hari

Mengakses Exception dengan as #

Exception yang tertangkap bisa diikat ke variabel dengan klausa except ... as e. Variabel tersebut adalah object exception utuh, sehingga kita bisa membaca class-nya dan isi pesannya:

python
umur_text = "2O"

try:
    umur = int(umur_text)
except ValueError as e:
    print("Tipe exception :", type(e).__name__)
    print("Isi pesan      :", e)
    print("Atribut args   :", e.args)

Output yang Dihasilkan:

text
Tipe exception : ValueError
Isi pesan      : invalid literal for int() with base 10: '2O'
Atribut args   : ("invalid literal for int() with base 10: '2O'",)

Mari kita telaah apa yang terjadi pada baris-baris kode di atas:

  1. Baris 4 (umur = int(umur_text)): string "2O" mengandung huruf O, bukan angka nol, sehingga konversi gagal dan ValueError dibangkitkan.
  2. Baris 5 (except ValueError as e:): interpreter Python mencocokkan class, lalu mengikat object exception ke variabel e.
  3. Baris 6–8 (print(...)): type(e).__name__ memberi nama class, e otomatis dikonversi str(e) menjadi pesan, dan e.args menampung argumen asli pembentuk exception.

Variabel e hanya hidup di dalam blok handler. Setelah blok except selesai, nama e dihapus dari scope — kita sudah membahas mekanisme scope pada Chapter Scope dan Namespace.

Satu blok try sering kali perlu bereaksi terhadap beberapa jenis kegagalan sekaligus. Cara mengaturnya menjadi bahasan Chapter Menangani Beberapa Exceptions.