try / except / else / finally

Alur lengkap penanganan exception dengan try, except, else, dan finally.

Daftar isi

Pernyataan try memungkinkan program menangkap kondisi gagal saat berjalan, alih-alih langsung berhenti dengan traceback. Objek yang mewakili kondisi gagal tersebut disebut exception. Mekanismenya disusun dalam empat blok yang saling melengkapi, yaitu try, except, else, dan finally. Topik ini membahas fungsi setiap blok beserta aturan urutannya, cara menangkap lebih dari satu jenis exception, dan kesalahan yang sering muncul ketika penangkapannya ditulis terlalu luas.

Struktur dasar try dan except#

Blok try berisi pernyataan yang berpotensi menimbulkan exception, sedangkan blok except berisi penanganan untuk jenis exception yang disebutkan setelah kata except. Apabila blok try selesai tanpa exception, blok except dilewati sepenuhnya. Apabila exception yang terjadi cocok dengan jenis yang ditangkap, eksekusi berpindah ke blok except, lalu program berlanjut ke pernyataan sesudah pernyataan try. Pola ini menjaga program tetap berjalan pada kondisi gagal yang dapat diantisipasi, misalnya masukan yang tidak sesuai format.

python Contoh: menangkap ValueError dari konversi
try:
    angka = int("12a")
    print("konversi berhasil:", angka)
except ValueError:
    print("konversi gagal: teks bukan bilangan bulat")
print("program berlanjut")
text Keluaran
konversi gagal: teks bukan bilangan bulat
program berlanjut

Fungsi int() menimbulkan ValueError apabila teksnya bukan bilangan bulat. Karena exception itu ditangkap, program tidak mencetak traceback dan tidak berhenti, tetapi melanjutkan ke pernyataan terakhir. Sebaliknya, blok try yang berhasil, misalnya int("12"), menjalankan seluruh isinya dan melewati except tanpa jejak.

Kata kunci as mengikat objek exception ke sebuah nama, sehingga jenis dan pesannya dapat dibaca oleh program. Informasi itu berguna untuk log karena menyebut penyebab kegagalan secara lengkap.

python Contoh: mengikat objek exception dengan as
try:
    angka = int("x7")
except ValueError as e:
    print(type(e).__name__, "-", e)
text Keluaran
ValueError - invalid literal for int() with base 10: 'x7'

Pesan pada keluaran menyebut teks yang gagal dikonversi, sehingga penyebabnya jelas tanpa perlu membaca ulang kode. Pola ini dipakai pula pada contoh berikutnya agar setiap penanganan menyertakan informasi yang relevan. Objek exception juga membawa atribut dan metodenya sendiri, yang dibahas lebih lanjut pada topik hierarki exception.

Klausa else dan finally#

Urutan lengkapnya memiliki aturan eksekusi yang tegas. Blok else dijalankan hanya apabila blok try selesai tanpa exception, sehingga cocok untuk kode yang hanya sah setelah operasi utamanya berhasil. Blok finally dijalankan selalu, baik exception terjadi maupun tidak, dan tetap dijalankan pula ketika exception tidak tertangkap. Diagram berikut merangkum alurnya.

try dijalankanelse dijalankanexcept dijalankanfinally dijalankantanpa exceptionexception cocokprogram berlanjut
Alur eksekusi try, except, else, dan finally
python Contoh: keempat blok dalam satu fungsi
def baca_angka(teks):
    try:
        angka = int(teks)
    except ValueError:
        print("except: teks tidak dapat dikonversi")
        return None
    else:
        print("else: konversi berhasil")
        return angka
    finally:
        print("finally: selesai memproses", repr(teks))


print("hasil:", baca_angka("150"))
print("hasil:", baca_angka("1z5"))
text Keluaran
else: konversi berhasil
finally: selesai memproses '150'
hasil: 150
except: teks tidak dapat dikonversi
finally: selesai memproses '1z5'
hasil: None

Untuk masukan 150, blok try berhasil sehingga else mencetak pesan keberhasilannya, sedangkan finally tetap tercetak sebelum fungsi mengembalikan nilainya. Untuk masukan 1z5, blok except yang bekerja dan finally tetap tercetak sesudahnya. Urutan cetakan menunjukkan bahwa finally selalu menjadi blok terakhir yang dijalankan sebelum fungsi benar-benar kembali.

Kekuatan finally paling terlihat ketika exception tidak tertangkap di dalam fungsinya.

python Contoh: finally tetap dijalankan saat exception diteruskan
def proses(angka):
    try:
        hasil = 10 / angka
        print("hasil:", hasil)
    finally:
        print("finally: pembersihan tetap dijalankan")
    return hasil


try:
    proses(5)
    proses(0)
except ZeroDivisionError as e:
    print("ditangkap di luar:", type(e).__name__)
text Keluaran
hasil: 2.0
finally: pembersihan tetap dijalankan
finally: pembersihan tetap dijalankan
ditangkap di luar: ZeroDivisionError

Exception ZeroDivisionError timbul di dalam pemanggilan proses(0), tetapi blok finally milik fungsi itu tetap mencetak pesannya sebelum exception mencapai except di pemanggil. Inilah alasan finally digunakan untuk pembersihan yang tidak boleh tertinggal dalam keadaan apa pun, misalnya menutup koneksi atau melepaskan kunci (lock).

Menangkap beberapa jenis exception#

Satu pernyataan try boleh memiliki lebih dari satu klausa except. Klausa-klausa diperiksa berurutan dari atas ke bawah, dan hanya yang pertama cocok yang dijalankan. Karena itu, jenis yang lebih spesifik ditulis lebih dahulu, sedangkan jenis yang lebih umum ditulis di akhir. Beberapa jenis yang penanganannya sama dapat digabung dalam satu klausa berbentuk tuple.

python Contoh: dua klausa except untuk dua jenis
def bagi(a, b):
    try:
        hasil = a / b
    except ZeroDivisionError:
        print("except: pembagi tidak boleh nol")
        return None
    except TypeError:
        print("except: tipe argumen tidak cocok")
        return None
    else:
        print("else: hasil pembagian", hasil)
        return hasil


bagi(10, 2)
bagi(10, 0)
bagi(10, "2")
text Keluaran
else: hasil pembagian 5.0
except: pembagi tidak boleh nol
except: tipe argumen tidak cocok

Pembagian 10 dengan 2 berjalan normal melalui else. Pembagian dengan 0 memicu ZeroDivisionError, sedangkan string “2” memicu TypeError karena operator / tidak menerima campuran angka dan string. Kedua kegagalan itu ditangani klausa yang berbeda, sehingga pesannya masing-masing spesifik.

python Contoh: satu klausa dengan tuple tipe
for teks in ["12", None, "3x"]:
    try:
        angka = int(teks)
        print("valid:", angka)
    except (ValueError, TypeError) as e:
        print("ditolak:", type(e).__name__)
text Keluaran
valid: 12
ditolak: TypeError
ditolak: ValueError

Bentuk tuple menangkap ValueError dan TypeError dengan penanganan yang sama, dan objek exceptionnya tetap dapat diikat dengan as. Sebaliknya, apabila jenis yang ditulis tidak mencakup exception yang terjadi, misalnya hanya TypeError padahal yang terjadi ValueError, exception itu tidak tertangkap dan program berhenti dengan traceback.

Kesalahan umum#

Kesalahan pertama adalah menulis except tanpa jenis, yang biasa disebut bare except. Bentuk ini menangkap hampir semua exception, termasuk SystemExit dan KeyboardInterrupt yang seharusnya dibiarkan menghentikan program.

python Contoh: except tanpa jenis menangkap SystemExit
try:
    raise SystemExit("program ingin berhenti")
except:
    print("tertangkap oleh except tanpa jenis")
text Keluaran
tertangkap oleh except tanpa jenis

SystemExit biasanya muncul ketika fungsi sys.exit() dipanggil. Dengan except tanpa jenis, sinyal berhenti itu ikut tertangkap sehingga program tidak pernah selesai seperti seharusnya.

Kesalahan kedua adalah urutan klausa yang terbalik. Karena pemeriksaan berhenti pada klausa pertama yang cocok, except Exception yang ditulis di atas except ValueError akan menelan seluruh ValueError lebih dahulu, dan klausa yang spesifik tidak pernah tercapai. Aturannya sederhana, yaitu dari yang spesifik ke yang umum.

Kesalahan ketiga adalah letak klausa else. Klausa tersebut hanya sah ditulis sesudah seluruh except dan sebelum finally. Penulisan else sesudah finally ditolak interpreter dengan SyntaxError, dan else tanpa satu pun except juga tidak sah. Apabila yang dibutuhkan hanya jaminan pembersihan tanpa penanganan, pasangan try dan finally saja sudah cukup.

Ringkasan#

  • Blok try memuat pernyataan berisiko, blok except menangkap jenis yang disebutkan, dan kata kunci as mengikat objek exceptionnya.
  • Blok else dijalankan hanya apabila try selesai tanpa exception, sedangkan finally dijalankan selalu, termasuk ketika exception diteruskan ke pemanggil.
  • Klausa except diperiksa dari atas ke bawah dan hanya yang pertama cocok yang dijalankan, sehingga jenis yang spesifik ditulis lebih dahulu.
  • except tanpa jenis menangkap hampir semua exception, termasuk SystemExit dan KeyboardInterrupt, sehingga jenisnya selalu disebutkan secara eksplisit.

Referensi#