Menu

Jenis error Python dan debugging: membaca traceback dan memperbaiki error umum

Tur error Python yang paling sering kamu temui, seperti KeyError, ValueError, ModuleNotFoundError, dan EOFError, beserta kebiasaan debugging yang memperbaikinya dengan cepat.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Error adalah cara Python memberi tahu apa yang terjadi

Setiap error Python adalah objek dengan sebuah tipe, pesan, dan traceback, yaitu rangkaian pemanggilan yang mengarah ke error itu. Membaca error dengan baik adalah keterampilan debugging terpenting yang bisa kamu pelajari. Halaman ini adalah tur error yang benar-benar akan kamu temui, dan kebiasaan yang membuat perbaikannya cepat.

Untuk pembahasan lebih dalam tentang mekanisme try/except dan cara memunculkan error sendiri, halaman Exception membahas sintaksnya. Halaman ini membahas error-error spesifik dan cara membacanya.

Membaca traceback

Jalankan sesuatu yang rusak:

def divide(a, b):
    return a / b

def report(values):
    for v in values:
        print(divide(10, v))

report([5, 2, 0])

Python mencetak sesuatu seperti ini:

Traceback (most recent call last):
  File "script.py", line 8, in <module>
    report([5, 2, 0])
  File "script.py", line 6, in report
    print(divide(10, v))
  File "script.py", line 2, in divide
    return a / b
ZeroDivisionError: division by zero

Baca dari bawah ke atas:

  1. ZeroDivisionError: division by zero: jenis exception dan pesannya. Ini apa yang salah.
  2. return a / b di divide, baris 2: baris yang sebenarnya memunculkan error.
  3. print(divide(10, v)) di report, baris 6: pemanggilan yang memicunya.
  4. report([5, 2, 0]) di level modul, baris 8: tempat semuanya dimulai.

Frame paling bawah hampir selalu tempat perbaikannya. Kalau sebuah library melempar error jauh di bagian dalamnya, telusuri traceback ke atas sampai frame pertama di kode milikmu: itulah pemanggilan tempat kamu memberikan input yang salah.

Error yang paling sering kamu temui

NameError

"Name 'mesage' is not defined." Disebabkan salah ketik atau memakai variabel sebelum diberi nilai. Di versi terbaru, pesan error Python biasanya menyebutkan nama pengganti yang mungkin ("Did you mean 'message'?").

Perbaikan: cek ejaan dan scope-nya. Kalau nama itu hanya ada di dalam sebuah fungsi, kamu tidak bisa membacanya dari luar.

TypeError

"Can only concatenate str (not 'int') to str." Tipe yang salah untuk operasi itu. Contoh klasiknya: menjumlahkan string dengan angka, memanggil sesuatu yang tidak bisa dipanggil, atau memberikan jumlah argumen yang salah ke sebuah fungsi.

Perbaikan: konversi tipe secara eksplisit (str(30), int("30")) atau periksa apa yang sebenarnya kamu kirimkan. f-string biasanya lebih enak dibaca daripada penggabungan dengan + antar tipe yang berbeda: f"age: {30}".

ValueError

"Invalid literal for int() with base 10: 'hello'." Tipenya benar, karena int() menerima string, tapi nilainya tidak cocok. Sering terjadi dengan int(), float(), mengurai datetime, dan fungsi yang menerima argumen dengan batasan tertentu.

Perbaikan: validasi sebelum mengonversi, atau tangkap error-nya lalu tangani:

KeyError

"KeyError: 'charlie'." Key itu tidak ada di dict. Ada tiga perbaikan yang idiomatis, dipilih sesuai tujuanmu:

Untuk dict yang key-nya harus terisi otomatis saat belum ada, collections.defaultdict layak dilihat.

IndexError

"List index out of range." Kamu meminta posisi yang tidak dimiliki deretan itu.

Perbaikan: lindungi dengan pengecekan panjang, pakai -1 untuk merujuk elemen terakhir, atau pakai slicing (numbers[5:6] mengembalikan [], bukan memunculkan error).

AttributeError

"'NoneType' object has no attribute 'upper'." Kamu memanggil method pada sesuatu yang tidak memilikinya. Hampir selalu berarti sebuah variabel punya tipe yang tidak terduga, sering kali None padahal kamu mengharapkan nilai sungguhan.

Perbaikan: cari tahu dari mana None itu berasal. print(type(var)) atau breakpoint tepat sebelum error adalah cara tercepat. Fungsi yang "kadang gagal" biasanya mengembalikan None; cek nilai kembaliannya sebelum memanggil method padanya.

ModuleNotFoundError (dan ImportError)

import fastapi

"No module named 'fastapi'." Package itu tidak terinstal di interpreter Python yang dipakai skripmu. Ada dua penyebab umum:

  1. Kamu memang belum menginstalnya. Jalankan python -m pip install fastapi di environment yang benar.
  2. Kamu sudah menginstalnya, tapi ke Python yang lain. Ini sering sekali terjadi di macOS saat pip dan python menunjuk ke instalasi yang berbeda.

Perbaikan yang andal adalah menginstal dengan interpreter yang sama dengan yang kamu pakai untuk menjalankan:

python -m pip install fastapi

Kalau kamu memakai virtual environment (dan sebaiknya begitu), pastikan virtual environment itu aktif sebelum menjalankan pip install maupun python script.py.

FileNotFoundError

with open("settings.yaml") as f:
    config = f.read()

"[Errno 2] No such file or directory: 'settings.yaml'." Path itu tidak ada, relatif terhadap tempat skrip dijalankan.

Perbaikan: cetak os.getcwd() di awal skrip untuk memastikan di mana Python mencari. Pakai path absolut atau pathlib.Path(__file__).parent / "settings.yaml" agar path selalu berpatokan pada lokasi skrip itu sendiri.

EOFError

name = input("Name: ")

"EOF when reading a line." input() mencoba membaca dari stdin tapi tidak mendapat apa-apa: entah input dialirkan dari sumber kosong, atau kamu menekan Ctrl-D di prompt.

Perbaikan: kalau input dari pipe memang wajar, bungkus pemanggilannya:

try:
    name = input("Name: ")
except EOFError:
    name = "anonymous"

Di editor browser pada dokumentasi ini, runtime-nya menyimulasikan input, jadi kamu tidak akan mengalami error ini di sini.

IndentationError dan SyntaxError

IndentationError: expected an indented block after function definition on line 2

Kedua error ini istimewa: keduanya muncul sebelum programmu berjalan. Python menolak mengurai file-nya.

  • IndentationError: badan sebuah def, if, for, dan sebagainya hilang atau tidak sejajar. Kebanyakan editor menampilkan indentasi secara visual; nyalakan "show whitespace" untuk menemukan campuran tab dan spasi.
  • SyntaxError: kamu lupa titik dua, tanda kurung tidak berpasangan, atau salah mengeja kata kunci. Versi Python terbaru menunjukkan panah (^) ke karakter yang bermasalah.

Perbaikan: pesan error-nya menyebutkan barisnya. Lihat baris itu. Kalau tidak ada yang jelas salah di sana, cek baris di atasnya: tanda kurung yang tidak ditutup beberapa baris sebelumnya sering muncul sebagai syntax error jauh di bawahnya.

RuntimeError

Error serba guna untuk "ada yang salah saat program berjalan, dan bukan salah satu error yang lebih spesifik." RecursionError (melebihi batas kedalaman rekursi) adalah turunan yang umum. Kode library sering memunculkan RuntimeError saat berada dalam keadaan yang tidak beres.

Perbaikan: baca pesannya; biasanya cukup jelas. Kalau penyebabnya rekursi, ubah menjadi perulangan iteratif, atau dalam kasus yang jarang, naikkan batasnya dengan sys.setrecursionlimit.

Debugging dengan print

Sebelum memakai debugger sungguhan, print(), atau lebih baik lagi bentuk f"{var=}", sudah bisa menangkap sebagian besar bug:

f"{var=}" mencetak teks ekspresinya sekaligus nilainya, jadi kamu tidak perlu mengetik ulang namanya di string format. Jalankan skripnya, telusuri output-nya, lalu temukan baris tempat sebuah nilai mulai salah. Kebanyakan bug "misterius" jadi jelas dengan tiga atau empat print yang ditempatkan dengan baik.

Bersihkan print itu sebelum commit. logging.debug(...) lebih baik daripada print untuk kode yang akan kamu rilis, karena kamu bisa menyalakan dan mematikan log debug tanpa mengubah baris kode.

breakpoint() dan pdb

Kalau print tidak cukup, breakpoint() membawamu masuk ke debugger interaktif Python di titik itu:

def discount(price, percent):
    breakpoint()
    return price * (1 - percent / 100)

discount(100, 20)

Jalankan skrip di terminal sungguhan. Kamu akan sampai di prompt (Pdb). Beberapa perintah yang perlu diketahui:

  • p variable: cetak sebuah variabel.
  • n: lanjut ke baris berikutnya.
  • s: masuk ke dalam pemanggilan fungsi.
  • c: lanjutkan sampai breakpoint berikutnya atau sampai selesai.
  • q: keluar.
  • l: tampilkan kode di sekitar baris saat ini.

Debugger di IDE (VS Code, PyCharm) membungkus protokol yang sama dalam GUI: breakpoint dipasang di margin, dan ada sidebar yang menampilkan variabel. Pilih yang terasa paling praktis bagimu.

Kebiasaan yang mengurangi error yang kamu temui

  • Pakai nama variabel yang deskriptif. Separuh gangguan TypeError dan AttributeError hilang kalau kamu tidak mungkin lupa isi sebuah variabel.
  • Validasi input di batasnya. Urai dan cek input pengguna atau isi file sekali, di awal fungsi. Sisa kode lalu bisa memercayai nilainya.
  • Gagal dengan jelas, bukan diam-diam. except Exception: pass tanpa penanganan menyembunyikan error yang sebenarnya perlu kamu lihat. Tangkap exception yang spesifik, tangani dengan sengaja, dan biarkan sisanya merambat.
  • Baca bagian bawah traceback lebih dulu. Setiap menit yang kamu pakai untuk belajar membaca traceback akan terbayar berkali-kali lipat.

Kebanyakan error bukan misteri: biasanya salah ketik satu baris atau kesalahan tipe dengan pesan yang jelas. Percayai pesan error-nya; biasanya pesan itu benar.

Kamu berhasil sampai sini

Itulah akhir bagian referensi. Kamu sudah melewati "apa itu Python?" sampai variabel, alur kontrol, koleksi, fungsi, class, iterasi, data dunia nyata, dan error. Dari sini, langkah berikutnya berbentuk proyek: pilih sesuatu yang ingin kamu buat, lalu telusuri mundur bagian-bagian yang perlu kamu pelajari lebih dalam. Halaman-halaman ini akan tetap ada saat kamu kembali dengan pertanyaan yang spesifik.

Pertanyaan yang sering diajukan

Apa itu KeyError di Python?

KeyError dimunculkan saat kamu mencari key dict yang tidak ada. users["missing"] memunculkan KeyError: 'missing'. Alternatif yang aman adalah users.get("missing", default), users.get("missing") (mengembalikan None), atau pengecekan eksplisit if key in users:.

Apa itu EOFError di Python?

EOFError (end-of-file) dimunculkan saat input() tidak bisa membaca apa pun karena aliran input sudah tertutup. Kamu paling sering melihatnya saat skrip yang memakai input() dijalankan lewat pipe tanpa data, atau saat kamu menekan Ctrl-D di prompt interaktif. Lindungi dengan try/except EOFError kalau skripmu harus menangani input dari pipe.

Apa itu ModuleNotFoundError?

ModuleNotFoundError berarti import X tidak menemukan modul bernama X. Bisa jadi package-nya belum diinstal (pip install X), atau sudah diinstal tapi di Python yang berbeda dari yang menjalankan kodemu (sangat umum kalau kamu punya beberapa Python). python -m pip install X memperbaiki kasus kedua karena memakai interpreter yang sama.

Bagaimana cara membaca traceback Python?

Baca dari bawah ke atas. Baris terakhir adalah jenis exception dan pesannya, yaitu hal spesifik yang salah. Baris-baris di atasnya menunjukkan call stack yang mengarah ke sana, dan kodemu sendiri biasanya ada di dekat bagian bawah. Klik atau buka file dan baris di frame paling bawah yang merupakan kodemu; di situlah perbaikannya.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai