Python & AI Tutorials Logo
Pemrograman Python

24. Memahami Error dan Traceback

Error adalah bagian yang tidak terhindarkan dalam pemrograman. Setiap programmer, dari pemula sampai ahli, mengalaminya secara rutin. Perbedaan antara kesulitan menghadapi error dan belajar darinya terletak pada pemahaman tentang apa yang Python coba sampaikan saat ada sesuatu yang salah.

Saat Python menemukan masalah di kode kamu, ia tidak hanya berhenti diam-diam—Python memberikan informasi detail tentang apa yang salah, di mana itu terjadi, dan sering kali memberi petunjuk tentang mengapa. Belajar membaca dan menafsirkan pesan error ini adalah salah satu skill paling berharga yang bisa kamu kembangkan sebagai programmer.

Di bab ini, kita akan membahas dua kategori utama error yang akan kamu temui: syntax error (masalah pada cara kamu menulis kode) dan runtime exception (masalah yang terjadi saat kode berjalan). Kita akan belajar membaca traceback—laporan error detail dari Python—dan memahami bagaimana exception mengubah alur normal program kamu. Yang paling penting, kita akan membangun mindset debugging yang memandang error bukan sebagai kegagalan, melainkan sebagai informasi berharga yang membantu kamu menulis kode yang lebih baik.

24.1) Syntax Error vs Runtime Exception

Python membedakan dua jenis masalah yang secara fundamental berbeda di kode kamu: syntax error dan runtime exception. Memahami perbedaan ini membantu kamu mendiagnosis masalah lebih cepat dan tahu harus mencari solusi di mana.

24.1.1) Apa Itu Syntax Error

Sebuah syntax error terjadi ketika Python tidak bisa memahami kode kamu karena melanggar aturan tata bahasa (grammar) bahasa tersebut. Sama seperti "The cat sat on the" adalah kalimat bahasa Inggris yang tidak lengkap, kode dengan syntax error adalah Python yang tidak lengkap atau salah format sehingga interpreter tidak bisa mem-parse-nya.

Syntax error terdeteksi sebelum program kamu berjalan. Python membaca seluruh skrip kamu terlebih dahulu, memastikan semuanya mengikuti aturan bahasa. Jika ia menemukan syntax error, Python menolak mengeksekusi bagian kode mana pun—bahkan bagian yang benar.

Berikut contoh sederhana:

python
# PERINGATAN: Syntax error - hanya untuk demonstrasi
# KESALAHAN: Tanda titik dua hilang setelah pernyataan if
age = 25
if age >= 18
    print("You are an adult")

Saat kamu mencoba menjalankan kode ini, Python langsung melaporkan:

  File "example.py", line 3
    if age >= 18
                ^
SyntaxError: expected ':'

Perhatikan beberapa fitur penting dari pesan error ini:

  1. File dan nomor baris: Python memberi tahu kamu dengan tepat di mana ia menemukan masalah (line 3)
  2. Indikator visual: Tanda caret (^) menunjukkan di mana Python mulai bingung
  3. Jenis error: SyntaxError dengan jelas mengidentifikasi ini sebagai masalah tata bahasa
  4. Petunjuk yang membantu: expected ':' memberi tahu apa yang kurang

Kode tidak pernah berjalan karena Python bahkan tidak bisa mulai mengeksekusinya—syntax-nya tidak valid.

Mari lihat syntax error umum lainnya:

python
# PERINGATAN: Syntax error - hanya untuk demonstrasi
# KESALAHAN: Tanda kurung tidak berpasangan
numbers = [1, 2, 3, 4, 5]
total = sum(numbers
print(f"Total: {total}")

Python melaporkan:

  File "example.py", line 2
    total = sum(numbers
               ^
SyntaxError: '(' was never closed

Di sini, Python mendeteksi bahwa kita membuka tanda kurung pada baris 2 tetapi tidak pernah menutupnya. Error dilaporkan pada baris 2 (di tempat tanda kurung yang tidak ditutup berada), dan caret menunjuk ke tempat Python mengharapkan menemukan tanda kurung penutup.

Karakteristik utama syntax error:

  • Terdeteksi sebelum kode apa pun berjalan
  • Mencegah seluruh program dieksekusi
  • Biasanya menunjukkan typo, tanda baca yang hilang, atau indentasi yang salah
  • Lokasi error mungkin sedikit setelah kesalahan sebenarnya

24.1.2) Apa Itu Runtime Exception

Sebuah runtime exception (atau cukup "exception") terjadi ketika kode yang secara syntax benar menemukan masalah saat dieksekusi. Kodenya adalah Python yang valid secara tata bahasa, tetapi ada sesuatu yang salah saat program benar-benar berjalan.

Berbeda dengan syntax error, exception terjadi saat program kamu berjalan. Python berhasil mem-parse kode kamu dan mulai mengeksekusinya, tetapi kemudian menemukan situasi yang tidak bisa ditangani.

Berikut contoh sederhana:

python
# Kode ini syntax-nya valid tetapi akan memunculkan exception
numbers = [10, 20, 30]
print(numbers[0])  # Output: 10
print(numbers[5])  # Baris ini akan memunculkan IndexError
print("This line never executes")

Output:

10
Traceback (most recent call last):
  File "example.py", line 3, in <module>
    print(numbers[5])
          ~~~~~~~^^^
IndexError: list index out of range

Perhatikan apa yang terjadi:

  1. Pernyataan print pertama dieksekusi dengan sukses (kita melihat 10)
  2. print kedua mencoba mengakses indeks 5, yang tidak ada
  3. Python memunculkan exception IndexError
  4. Program berhenti, dan print ketiga tidak pernah dieksekusi

Kodenya benar secara syntax—Python tidak bermasalah memahami apa yang ingin kita lakukan. Masalah muncul saat eksekusi ketika kita mencoba mengakses elemen list yang tidak ada.

Berikut contoh lain yang menunjukkan jenis runtime exception yang berbeda:

python
# Syntax valid, tetapi pembagian dengan nol saat runtime
def calculate_average(total, count):
    return total / count
 
# Ini berjalan baik
print(calculate_average(100, 4))  # Output: 25.0
print(calculate_average(75, 3))   # Output: 25.0
 
# Ini memunculkan exception
print(calculate_average(50, 0))   # ZeroDivisionError

Output:

25.0
25.0
Traceback (most recent call last):
  File "example.py", line 8, in <module>
    print(calculate_average(50, 0))
          ^^^^^^^^^^^^^^^^^^^^^^^^
  File "example.py", line 2, in calculate_average
    return total / count
           ~~~~~~^~~~~~~
ZeroDivisionError: division by zero

Fungsi bekerja sempurna dua kali, tetapi pada pemanggilan ketiga, kita mengirim 0 sebagai count, menyebabkan pembagian dengan nol. Python tidak bisa mendeteksi masalah ini sampai kode benar-benar dijalankan dengan nilai tersebut.

Karakteristik utama runtime exception:

  • Terjadi saat eksekusi program
  • Kodenya valid secara syntax
  • Sering bergantung pada data atau kondisi tertentu
  • Program berjalan sampai titik di mana exception terjadi
  • Input yang berbeda bisa memunculkan exception yang berbeda (atau tidak ada sama sekali)

24.1.3) Membandingkan Syntax Error dan Runtime Exception

Mari lihat kedua jenis error ini berdampingan untuk memahami perbedaannya:

python
# Contoh 1: Syntax Error
# KESALAHAN: Tanda kutip penutup hilang
print("Program started!")
message = "Hello, world
print(message)

Ini langsung menghasilkan syntax error:

  File "example.py", line 4
    message = "Hello, world
              ^
SyntaxError: unterminated string literal (detected at line 4)

Penting: Perhatikan bahwa kamu tidak melihat "Program started!" di output. Python mendeteksi syntax error sebelum menjalankan kode apa pun.

Sekarang bandingkan dengan runtime exception:

python
# Contoh 2: Runtime Exception
# Syntax valid, tetapi variabelnya tidak ada
print("Program started!")
message = "Hello, world"
print(mesage)  # Typo: 'mesage' bukannya 'message'

Output:

Program started!
Traceback (most recent call last):
  File "example.py", line 5, in <module>
    print(mesage)
          ^^^^^^
NameError: name 'mesage' is not defined

Penting: Kali ini kamu melihat "Program started!" di output. Python berhasil menjalankan dua print pertama dan pernyataan assignment (baris 3-4), tetapi menemukan masalah pada baris 5 saat mencoba mencari mesage.

Perbedaan utamanya: Pada contoh pertama, Python bahkan tidak pernah mencoba menjalankan kode—Python menemukan syntax error saat parsing. Pada contoh kedua, Python berhasil mulai mengeksekusi program dan menjalankan beberapa baris sebelum menemukan runtime error.

Tidak

Ya

Tidak

Ya

Python Membaca Kode Kamu

Syntax Valid?

Syntax Error
Program Tidak Pernah Berjalan

Program Mulai Dieksekusi

Ada Masalah Selama
Eksekusi?

Program Selesai
Dengan Sukses

Runtime Exception
Program Berhenti

24.2) Jenis Exception Bawaan yang Umum

Python punya banyak jenis exception bawaan, masing-masing mewakili jenis masalah tertentu. Belajar mengenali exception yang umum ini membantu kamu cepat memahami apa yang salah dan cara memperbaikinya. Setiap jenis exception punya nama deskriptif yang memberi petunjuk tentang masalahnya.

24.2.1) NameError: Menggunakan Nama yang Belum Didefinisikan

Sebuah NameError terjadi ketika kamu mencoba menggunakan variabel, fungsi, atau nama lain yang tidak dikenali Python. Ini biasanya berarti kamu lupa mendefinisikan sesuatu, salah mengeja nama, atau mencoba menggunakan sesuatu sebelum dibuat.

python
# Contoh 1: Lupa mendefinisikan variabel
print(greeting)  # NameError: name 'greeting' is not defined

Output:

Traceback (most recent call last):
  File "example.py", line 2, in <module>
    print(greeting)
          ^^^^^^^^
NameError: name 'greeting' is not defined

Python memberi tahu bahwa ia tidak tahu apa itu greeting. Kamu perlu membuatnya terlebih dahulu:

python
# Versi yang benar
greeting = "Hello, Python!"
print(greeting)  # Output: Hello, Python!

Berikut contoh yang lebih halus dengan typo:

python
# Contoh 2: Typo pada nama variabel
user_name = "Alice"
age = 30
 
print(f"{username} is {age} years old")  # NameError: name 'username' is not defined

Kita mendefinisikan user_name (dengan underscore) tetapi mencoba menggunakan username (tanpa underscore). Python menganggap ini sebagai nama yang sepenuhnya berbeda.

24.2.2) TypeError: Tipe yang Salah untuk Suatu Operasi

Sebuah TypeError terjadi ketika kamu mencoba melakukan operasi pada nilai dengan tipe yang salah. Misalnya, kamu tidak bisa menambahkan string ke integer, atau memanggil sesuatu yang bukan fungsi.

python
# Contoh 1: Mencampur tipe yang tidak kompatibel
age = 25
message = "You are " + age + " years old"  # TypeError

Output:

Traceback (most recent call last):
  File "example.py", line 2, in <module>
    message = "You are " + age + " years old"
              ~~~~~~~~~~~~^~~~~
TypeError: can only concatenate str (not "int") to str

Python memberi tahu bahwa operator + bisa menggabungkan string dengan string, tetapi tidak string dengan integer. Kamu perlu mengonversi integer ke string:

python
# Versi yang benar
age = 25
message = "You are " + str(age) + " years old"
print(message)  # Output: You are 25 years old

TypeError juga terjadi ketika kamu memberikan jumlah argumen yang salah ke sebuah fungsi:

python
# Contoh 3: Jumlah argumen salah
def calculate_area(length, width):
    return length * width
 
area = calculate_area(5)  # TypeError: missing 1 required positional argument

Output:

Traceback (most recent call last):
  File "example.py", line 4, in <module>
    area = calculate_area(5)
TypeError: calculate_area() missing 1 required positional argument: 'width'

Fungsi mengharapkan dua argumen, tetapi kita hanya memberikan satu.

24.2.3) ValueError: Tipe Benar, Nilainya Salah

Sebuah ValueError terjadi ketika kamu memberikan nilai dengan tipe yang benar, tetapi nilai itu sendiri tidak sesuai untuk operasi tersebut. Tipenya tepat, tetapi nilai spesifiknya tidak masuk akal dalam konteks itu.

python
# Contoh 1: Mengonversi string tidak valid menjadi integer
user_input = "twenty-five"
age = int(user_input)  # ValueError: invalid literal for int()

Output:

Traceback (most recent call last):
  File "example.py", line 2, in <module>
    age = int(user_input)
ValueError: invalid literal for int() with base 10: 'twenty-five'

Fungsi int() mengharapkan string, dan kita memberinya string—jadi tipenya benar. Namun string "twenty-five" tidak bisa dikonversi menjadi integer karena berisi huruf. String "25" akan bekerja baik:

python
# Versi yang benar
user_input = "25"
age = int(user_input)
print(age)  # Output: 25

ValueError juga terjadi pada method list:

python
# Contoh 3: Menghapus item yang tidak ada
fruits = ["apple", "banana", "orange"]
fruits.remove("grape")  # ValueError: 'grape' is not in list

Output:

Traceback (most recent call last):
  File "example.py", line 2, in <module>
    fruits.remove("grape")
    ~~~~~~~~~~~~~^^^^^^^^^
ValueError: list.remove(x): x not in list

Method remove() mengharapkan nilai yang memang ada di dalam list. Kita sebaiknya mengecek dulu:

python
# Versi yang benar
fruits = ["apple", "banana", "orange"]
if "grape" in fruits:
    fruits.remove("grape")
else:
    print("Grape not found in list")  # Output: Grape not found in list

24.2.4) IndexError: Indeks Sequence Tidak Valid

Sebuah IndexError terjadi ketika kamu mencoba mengakses sequence (list, tuple, string) menggunakan indeks yang tidak ada. Ingat bahwa Python memakai indeks berbasis nol, dan indeks valid berada pada rentang 0 sampai len(sequence) - 1.

python
# Contoh 1: Indeks terlalu besar
colors = ["red", "green", "blue"]
print(colors[0])  # Output: red
print(colors[3])  # IndexError: list index out of range

Output:

red
Traceback (most recent call last):
  File "example.py", line 3, in <module>
    print(colors[3])
          ~~~~~~^^^
IndexError: list index out of range

List memiliki tiga elemen pada indeks 0, 1, dan 2. Indeks 3 tidak ada. Ini kesalahan yang sangat umum saat kamu lupa bahwa indeks dimulai dari 0:

python
# Versi yang benar
colors = ["red", "green", "blue"]
print(colors[2])  # Output: blue (elemen ketiga)

24.2.5) KeyError: Key Dictionary Tidak Ada

Sebuah KeyError terjadi ketika kamu mencoba mengakses key dictionary yang tidak ada. Tidak seperti list di mana kamu bisa mengecek panjangnya, dictionary bisa punya key apa pun, jadi kamu perlu memastikan key itu ada sebelum mengaksesnya.

python
# Contoh 1: Mengakses key yang tidak ada
student = {
    "name": "Alice",
    "age": 20,
    "major": "Computer Science"
}
 
print(student["name"])   # Output: Alice
print(student["grade"])  # KeyError: 'grade'

Output:

Alice
Traceback (most recent call last):
  File "example.py", line 7, in <module>
    print(student["grade"])
          ~~~~~~~^^^^^^^^^
KeyError: 'grade'

Dictionary tidak punya key "grade". Kamu bisa mengecek apakah key ada terlebih dahulu:

python
# Versi yang benar menggunakan 'in'
student = {
    "name": "Alice",
    "age": 20,
    "major": "Computer Science"
}
 
if "grade" in student:
    print(student["grade"])
else:
    print("Grade not available")  # Output: Grade not available

Atau gunakan method get(), yang mengembalikan None (atau nilai default) alih-alih memunculkan error:

python
# Alternatif menggunakan get()
grade = student.get("grade")
if grade is not None:
    print(f"Grade: {grade}")
else:
    print("Grade not available")  # Output: Grade not available

KeyError sering terjadi saat memproses data dengan struktur yang tidak konsisten:

python
# Contoh 2: Memproses banyak record
students = [
    {"name": "Alice", "age": 20, "grade": "A"},
    {"name": "Bob", "age": 21},  # Key 'grade' tidak ada
    {"name": "Carol", "age": 19, "grade": "B"}
]
 
for student in students:
    print(f"{student['name']}: {student['grade']}")  # KeyError pada Bob

Output:

Alice: A
Traceback (most recent call last):
  File "example.py", line 7, in <module>
    print(f"{student['name']}: {student['grade']}")
                                ~~~~~~~^^^^^^^^^
KeyError: 'grade'

Gunakan get() dengan nilai default untuk menangani key yang hilang dengan rapi:

python
# Versi yang benar
students = [
    {"name": "Alice", "age": 20, "grade": "A"},
    {"name": "Bob", "age": 21},
    {"name": "Carol", "age": 19, "grade": "B"}
]
 
for student in students:
    grade = student.get("grade", "Not assigned")
    print(f"{student['name']}: {grade}")

Output:

Alice: A
Bob: Not assigned
Carol: B

24.2.6) AttributeError: Akses Atribut yang Tidak Valid

Sebuah AttributeError terjadi ketika kamu mencoba mengakses atribut atau method yang tidak ada pada sebuah objek. Ini sering terjadi ketika kamu tertukar method antar tipe yang berbeda atau salah mengeja nama atribut.

python
# Contoh 1: Method yang salah untuk tipe tersebut
numbers = [1, 2, 3, 4, 5]
numbers.append(6)  # Ini berfungsi - list punya append()
print(numbers)     # Output: [1, 2, 3, 4, 5, 6]
 
text = "Hello"
text.append("!")   # AttributeError: 'str' object has no attribute 'append'

Output:

[1, 2, 3, 4, 5, 6]
Traceback (most recent call last):
  File "example.py", line 6, in <module>
    text.append("!")
    ^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'append'

String tidak punya method append() karena string bersifat immutable. Kamu perlu memakai concatenation atau method string lainnya:

python
# Versi yang benar
text = "Hello"
text = text + "!"  # Concatenation
print(text)        # Output: Hello!

AttributeError juga terjadi karena typo:

python
# Contoh 2: Salah eja nama method
message = "Python Programming"
result = message.uppper()  # AttributeError: 'str' object has no attribute 'uppper'

Output:

Traceback (most recent call last):
  File "example.py", line 2, in <module>
    result = message.uppper()
             ^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'uppper'. Did you mean: 'upper'?

Perhatikan bahwa Python 3.10+ sering menyarankan ejaan yang benar! Method yang benar adalah upper():

python
# Versi yang benar
message = "Python Programming"
result = message.upper()
print(result)  # Output: PYTHON PROGRAMMING

24.2.7) ZeroDivisionError: Pembagian dengan Nol

Sebuah ZeroDivisionError terjadi ketika kamu mencoba membagi angka dengan nol, yang secara matematika tidak terdefinisi. Ini sering terjadi pada input pengguna atau nilai hasil perhitungan yang tidak kamu duga menjadi nol.

python
# Contoh 1: Pembagian langsung dengan nol
result = 10 / 0  # ZeroDivisionError: division by zero

Output:

Traceback (most recent call last):
  File "example.py", line 1, in <module>
    result = 10 / 0
             ~~~^~~
ZeroDivisionError: division by zero

Ini juga berlaku untuk floor division dan modulo:

python
# Contoh 2: Operasi pembagian lainnya
a = 10 // 0  # ZeroDivisionError
b = 10 % 0   # ZeroDivisionError

Contoh yang lebih realistis melibatkan perhitungan:

python
# Contoh 3: Menghitung rata-rata
def calculate_average(numbers):
    total = sum(numbers)
    count = len(numbers)
    return total / count
 
scores = [85, 90, 78, 92]
print(calculate_average(scores))  # Output: 86.25
 
empty_scores = []
print(calculate_average(empty_scores))  # ZeroDivisionError

Output:

86.25
Traceback (most recent call last):
  File "example.py", line 9, in <module>
    print(calculate_average(empty_scores))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "example.py", line 4, in calculate_average
    return total / count
           ~~~~~~^~~~~~~
ZeroDivisionError: division by zero

List kosong punya panjang 0, menyebabkan pembagian dengan nol. Selalu cek kondisi ini:

python
# Versi yang benar
def calculate_average(numbers):
    if len(numbers) == 0:
        return 0  # Atau return None, atau raise error yang lebih deskriptif
    
    total = sum(numbers)
    count = len(numbers)
    return total / count
 
scores = [85, 90, 78, 92]
print(calculate_average(scores))  # Output: 86.25
 
empty_scores = []
print(calculate_average(empty_scores))  # Output: 0

Jenis Exception Umum

NameError
Variabel/fungsi tidak terdefinisi

TypeError
Tipe salah untuk operasi

ValueError
Tipe benar, nilai salah

IndexError
Indeks sequence tidak valid

KeyError
Key dictionary tidak ada

AttributeError
Atribut/method tidak valid

ZeroDivisionError
Pembagian dengan nol

Memahami jenis exception umum ini membantu kamu mendiagnosis masalah dengan cepat. Saat kamu melihat sebuah exception, nama tipenya langsung memberi tahu kategori masalah yang terjadi, dan pesan error memberikan detail spesifik tentang apa yang salah.

24.3) Membaca dan Menafsirkan Traceback Secara Detail

Saat runtime exception terjadi, Python tidak hanya memberi tahu apa yang salah—Python memberikan traceback yang detail, menunjukkan dengan tepat bagaimana program kamu sampai ke titik itu. Belajar membaca traceback sangat penting untuk debugging yang efektif. Traceback itu seperti jejak remah roti yang menunjukkan jalur yang ditempuh program kamu sebelum menemui error.

24.3.1) Anatomi Traceback

Mari mulai dengan contoh sederhana dan periksa setiap bagian traceback:

python
# Program sederhana dengan error
def calculate_discount(price, discount_percent):
    discount_amount = price * (discount_percent / 100)
    final_price = price - discount_amount
    return final_price
 
def process_order(item_price, discount):
    discounted_price = calculate_discount(item_price, discount)
    tax = discounted_price * 0.08
    total = discounted_price + tax
    return total
 
# Program utama
original_price = "50"  # Ups! Ini seharusnya angka
discount_rate = 10
final_cost = process_order(original_price, discount_rate)
print(f"Final cost: ${final_cost:.2f}")

Output:

Traceback (most recent call last):
  File "example.py", line 16, in <module>
    final_cost = process_order(original_price, discount_rate)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "example.py", line 8, in process_order
    discounted_price = calculate_discount(item_price, discount)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "example.py", line 2, in calculate_discount
    discount_amount = price * (discount_percent / 100)
                      ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
TypeError: can't multiply sequence by non-int of type 'float'

Mari uraikan setiap komponen traceback ini:

1. Header: "Traceback (most recent call last):"

Baris ini memberi tahu kamu bahwa yang berikutnya adalah traceback—catatan pemanggilan fungsi. Frasa "most recent call last" berarti traceback ditampilkan dalam urutan kronologis: fungsi yang dipanggil pertama muncul di awal, dan lokasi tempat error benar-benar terjadi muncul terakhir.

2. Call Stack (Dibaca dari Atas ke Bawah):

  File "example.py", line 16, in <module>
    final_cost = process_order(original_price, discount_rate)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Ini adalah pemanggilan fungsi pertama dalam rantai. Ini menunjukkan:

  • Nama file: "example.py" - lokasi kode berada
  • Nomor baris: line 16 - baris persis yang melakukan pemanggilan ini
  • Konteks: in <module> - kode ini berada di level teratas (bukan di dalam fungsi)
  • Kode: Baris sebenarnya yang dieksekusi
  • Highlight: Karakter ^ menunjuk ke bagian spesifik dari baris yang terlibat

Konteks <module> berarti ini adalah kode yang berjalan di level module (bagian utama dari skrip kamu), bukan di dalam fungsi mana pun.

  File "example.py", line 8, in process_order
    discounted_price = calculate_discount(item_price, discount)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Ini adalah pemanggilan fungsi kedua. Fungsi process_order dipanggil dari baris 16, dan sekarang kita berada di dalam fungsi itu pada baris 8, di mana ia memanggil calculate_discount.

  File "example.py", line 2, in calculate_discount
    discount_amount = price * (discount_percent / 100)
                      ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~

Di sinilah error sebenarnya terjadi. Sekarang kita berada di dalam fungsi calculate_discount pada baris 2, dan inilah baris yang menyebabkan masalah.

3. Pesan Error:

TypeError: can't multiply sequence by non-int of type 'float'

Ini adalah error sebenarnya yang terjadi:

  • Jenis exception: TypeError - memberi tahu kategori error
  • Deskripsi: Sisanya menjelaskan secara spesifik apa yang salah

Dalam kasus ini, Python memberi tahu bahwa kita mencoba mengalikan sebuah sequence (string, dalam kasus ini) dengan float, yang tidak diizinkan.

24.3.2) Membaca Traceback dari Bawah ke Atas

Walaupun traceback dicetak dalam urutan kronologis (atas ke bawah), programmer berpengalaman sering membacanya dari bawah ke atas karena error sebenarnya ada di bagian bawah, dan baris-baris di atas menunjukkan bagaimana kita sampai ke sana.

Mari baca traceback sebelumnya dari bawah ke atas:

Langkah 1: Mulai dari pesan error

TypeError: can't multiply sequence by non-int of type 'float'

"Oke, kita mencoba mengalikan sebuah sequence dengan float. Itu tidak diizinkan."

Langkah 2: Lihat di mana error terjadi

  File "example.py", line 2, in calculate_discount
    discount_amount = price * (discount_percent / 100)
                      ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~

"Error terjadi di fungsi calculate_discount pada baris 2. Kita mencoba mengalikan price dengan sesuatu."

Langkah 3: Telusuri mundur untuk melihat bagaimana kita sampai di sana

  File "example.py", line 8, in process_order
    discounted_price = calculate_discount(item_price, discount)

"Fungsi calculate_discount dipanggil dari process_order pada baris 8, dengan item_price dikirim sebagai parameter price."

Langkah 4: Lanjutkan menelusuri mundur

  File "example.py", line 16, in <module>
    final_cost = process_order(original_price, discount_rate)

"Dan process_order dipanggil dari program utama pada baris 16, dengan original_price dikirim sebagai item_price."

Langkah 5: Temukan akar masalahnya

Sekarang kita bisa menelusuri masalahnya: original_price adalah "50" (sebuah string), yang diteruskan sebagai item_price ke process_order, lalu diteruskan sebagai price ke calculate_discount, tempat kita mencoba mengalikannya dengan float. Solusinya adalah menjadikan original_price sebagai angka:

python
# Versi yang diperbaiki
def calculate_discount(price, discount_percent):
    discount_amount = price * (discount_percent / 100)
    final_price = price - discount_amount
    return final_price
 
def process_order(item_price, discount):
    discounted_price = calculate_discount(item_price, discount)
    tax = discounted_price * 0.08
    total = discounted_price + tax
    return total
 
# Program utama - memperbaiki tipe datanya
original_price = 50  # Sekarang ini angka, bukan string
discount_rate = 10
final_cost = process_order(original_price, discount_rate)
print(f"Final cost: ${final_cost:.2f}")  # Output: Final cost: $48.60

Baca Traceback

1. Baca Pesan Error
Baris Paling Bawah
2. Temukan Lokasi Error
Blok Kode Terakhir
3. Telusuri Call Stack
Naik ke Atas
4. Buat Hipotesis
Apa yang Salah?
5. Verifikasi dan Perbaiki
Uji Solusi Kamu

24.3.3) Merangkum: Menjadikan Traceback sebagai Alat Debugging

Memahami cara membaca traceback mengubahnya dari dinding teks yang mengintimidasi menjadi alat debugging yang membantu. Setiap baris memberi informasi berharga tentang jalur eksekusi program kamu, dan dengan latihan, kamu akan bisa cepat mengidentifikasi dan memperbaiki masalah dengan mengikuti petunjuk dari traceback.

24.4) Bagaimana Exception Mengubah Alur Normal Program

Saat sebuah exception terjadi, ia tidak hanya menghentikan program kamu—ia secara fundamental mengubah cara program dieksekusi. Memahami perilaku ini sangat penting untuk menulis kode yang tangguh dan untuk memahami apa yang terjadi saat error muncul.

24.4.1) Alur Program Normal vs Alur Exception

Dalam eksekusi normal, Python menjalankan kode kamu baris demi baris, dari atas ke bawah:

python
# Alur program normal
print("Step 1: Starting calculation")
result = 10 + 5
print(f"Step 2: Result is {result}")
final = result * 2
print(f"Step 3: Final value is {final}")
print("Step 4: Program complete")

Output:

Step 1: Starting calculation
Step 2: Result is 15
Step 3: Final value is 30
Step 4: Program complete

Setiap baris dieksekusi berurutan. Sekarang mari lihat apa yang terjadi saat exception terjadi:

python
# Alur program dengan exception
print("Step 1: Starting calculation")
result = 10 / 0  # Ini memunculkan ZeroDivisionError
print(f"Step 2: Result is {result}")  # Ini tidak pernah dieksekusi
final = result * 2  # Ini tidak pernah dieksekusi
print(f"Step 3: Final value is {final}")  # Ini tidak pernah dieksekusi
print("Step 4: Program complete")  # Ini tidak pernah dieksekusi

Output:

Step 1: Starting calculation
Traceback (most recent call last):
  File "example.py", line 2, in <module>
    result = 10 / 0
             ~~~^~~
ZeroDivisionError: division by zero

Perhatikan bahwa hanya pernyataan print pertama yang dieksekusi. Begitu exception terjadi pada baris 2, Python berhenti mengeksekusi sisa kode. Exception menginterupsi alur normal.

24.4.2) Exception Merambat Naik pada Call Stack

Saat exception terjadi di dalam sebuah fungsi, Python tidak hanya berhenti pada fungsi itu—Python akan merambat (naik) melalui call stack sampai ada sesuatu yang menanganinya atau program berhenti.

python
# Contoh 1: Exception merambat melalui fungsi-fungsi
def calculate_average(numbers):
    total = sum(numbers)
    count = len(numbers)
    return total / count  # Bisa memunculkan ZeroDivisionError
 
def process_scores(score_list):
    print("Processing scores...")
    avg = calculate_average(score_list)
    print(f"Average calculated: {avg}")
    return avg
 
def main():
    print("Program starting")
    scores = []  # List kosong
    result = process_scores(scores)
    print(f"Final result: {result}")
    print("Program ending")
 
main()

Output:

Program starting
Processing scores...
Traceback (most recent call last):
  File "example.py", line 18, in <module>
    main()
  File "example.py", line 14, in main
    result = process_scores(scores)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "example.py", line 9, in process_scores
    avg = calculate_average(score_list)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "example.py", line 4, in calculate_average
    return total / count
           ~~~~~~^~~~~~~
ZeroDivisionError: division by zero

Mari telusuri apa yang terjadi:

  1. main() mulai berjalan dan mencetak "Program starting"
  2. main() memanggil process_scores()
  3. process_scores() mencetak "Processing scores..."
  4. process_scores() memanggil calculate_average()
  5. calculate_average() mencoba membagi dengan nol
  6. Exception terjadi dan merambat naik:
    • calculate_average() berhenti seketika (tidak mengembalikan nilai)
    • Kontrol kembali ke process_scores(), tetapi bukan secara normal—exception terus merambat
    • process_scores() berhenti seketika (print setelah calculate_average() tidak pernah dieksekusi)
    • Kontrol kembali ke main(), tetapi lagi-lagi exception terus merambat
    • main() berhenti seketika (print setelah process_scores() tidak pernah dieksekusi)
  7. Program berhenti dengan traceback

Tidak ada kode setelah exception yang dieksekusi di fungsi mana pun. Exception “menggelembung naik” melalui semua pemanggilan fungsi sampai mencapai level teratas dan menghentikan program.

24.5) Mindset Debugging: Menganggap Error sebagai Informasi, Bukan Kegagalan

Salah satu skill paling penting dalam pemrograman bukan menulis kode yang sempurna—melainkan belajar bekerja secara efektif dengan kode yang tidak sempurna. Setiap programmer, apa pun level pengalamannya, menulis kode yang menghasilkan error. Perbedaan antara programmer yang kesulitan dan yang efektif bukan pada menghindari error, tetapi pada bagaimana mereka meresponsnya.

24.5.1) Error Bukanlah Kegagalan

Saat kamu belajar pemrograman, wajar kalau kamu merasa frustrasi ketika menemui error. Kamu mungkin merasa kamu melakukan sesuatu yang salah atau kamu “nggak paham-paham.” Mindset ini tidak produktif dan, yang lebih penting, tidak akurat.

Error bukanlah kegagalan—error adalah feedback.

Anggap error seperti GPS yang menghitung ulang rute kamu. Saat kamu salah belok, GPS tidak bilang “Kamu gagal!” Ia bilang “Recalculating route” dan memberi arahan baru. Pesan error Python bekerja dengan cara yang sama: mereka memberi tahu bahwa jalur yang kamu ambil tidak berhasil, dan mereka memberikan informasi untuk membantu kamu menemukan jalur yang berhasil.

Pertimbangkan contoh sederhana ini:

python
# Percobaan pertama menghitung rata-rata
def calculate_average(numbers):
    total = sum(numbers)
    average = total / len(numbers)
    return average
 
scores = []
result = calculate_average(scores)
print(f"Average: {result}")

Output:

Traceback (most recent call last):
  File "example.py", line 8, in <module>
    result = calculate_average(scores)
             ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "example.py", line 4, in calculate_average
    average = total / len(numbers)
              ~~~~~~^~~~~~~~~~~~~~
ZeroDivisionError: division by zero

Error ini tidak mengatakan bahwa kamu programmer yang buruk. Ia mengatakan sesuatu yang spesifik dan berguna: “Kamu mencoba membagi dengan nol, yang terjadi saat list kosong. Kamu perlu menangani kasus itu.”

Dengan informasi ini, kamu bisa memperbaiki kode kamu:

python
# Versi yang ditingkatkan berdasarkan feedback error
def calculate_average(numbers):
    if len(numbers) == 0:
        return 0  # Atau return None, atau raise error yang lebih deskriptif
    
    total = sum(numbers)
    average = total / len(numbers)
    return average
 
scores = []
result = calculate_average(scores)
print(f"Average: {result}")  # Output: Average: 0

Error tersebut membantu kamu menulis kode yang lebih baik. Tanpa error itu, kamu mungkin tidak menyadari bahwa fungsi kamu tidak bisa menangani list kosong.

24.5.2) Setiap Error Mengajarkan Sesuatu

Setiap error yang kamu temui mengajarkan sesuatu tentang Python, tentang kode kamu, atau tentang pemrograman secara umum. Mari lihat beberapa contoh tentang apa yang diajarkan oleh berbagai error:

Contoh 1: Belajar tentang tipe

python
# Mencoba menambahkan tipe yang tidak kompatibel
age = 25
message = "You are " + age + " years old"

Output:

TypeError: can only concatenate str (not "int") to str

Apa yang ini ajarkan: Python punya aturan tipe yang ketat. Kamu tidak bisa mencampur string dan angka dalam penggabungan. Error ini mengajarkan kompatibilitas tipe dan mengenalkan konsep konversi tipe.

Contoh 2: Belajar tentang struktur data

python
# Mencoba mengakses dictionary seperti list
student = {"name": "Alice", "age": 20}
first_value = student[0]

Output:

KeyError: 0

Apa yang ini ajarkan: Dictionary menggunakan key, bukan indeks numerik. Error ini mengajarkan perbedaan antara dictionary dan list, serta cara mengakses nilai dictionary dengan benar.

Contoh 3: Belajar tentang scope

python
# Mencoba menggunakan variabel sebelum mendefinisikannya
def greet():
    print(f"Hello, {name}!")
 
greet()
name = "Alice"

Output:

NameError: name 'name' is not defined

Apa yang ini ajarkan: Variabel harus didefinisikan sebelum digunakan, dan urutan eksekusi itu penting. Error ini mengajarkan scope variabel dan pentingnya inisialisasi.

Setiap error ini memberikan informasi spesifik dan bisa ditindaklanjuti yang membantu kamu memahami Python lebih baik. Alih-alih melihatnya sebagai hambatan, anggap ini sebagai kesempatan belajar.

24.5.3) Merangkul Mindset Debugging

Programmer profesional menghabiskan porsi waktu yang signifikan untuk debugging. Ini bukan tanda kelemahan—ini bagian inti dari pekerjaan. Programmer terbaik bukan yang tidak pernah membuat kesalahan; mereka adalah yang:

  1. Mengharapkan error: Mereka tahu error akan terjadi dan tidak terkejut atau patah semangat
  2. Membaca error dengan teliti: Mereka mengambil informasi sebanyak mungkin dari pesan error
  3. Debug secara sistematis: Mereka mengikuti proses logis alih-alih membuat perubahan acak
  4. Belajar dari error: Mereka menjadikan setiap error sebagai kesempatan untuk memahami Python lebih baik
  5. Tetap penasaran: Mereka bertanya “Kenapa itu bisa terjadi?” alih-alih hanya “Gimana cara memperbaikinya?”

Tidak

Ya

Tidak

Ya

Menemui Error

Baca Pesan Error
dengan Teliti

Pahami Apa yang
Salah

Buat Hipotesis
tentang Penyebab

Uji Hipotesis
dengan Debug Output

Hipotesis
Benar?

Terapkan Perbaikan

Uji Solusi

Berjalan
Benar?

Belajar dari
Pengalaman

Lanjutkan
dengan Percaya Diri

Ingat: Setiap error adalah kesempatan untuk mempelajari sesuatu yang baru tentang Python, tentang pemrograman, atau tentang pemecahan masalah. Rangkul error sebagai feedback yang berharga, hadapi secara sistematis, dan rayakan keberhasilan debugging kamu. Mindset ini akan bermanfaat sepanjang perjalanan pemrograman kamu.


Memahami error dan traceback adalah hal yang mendasar untuk menjadi programmer Python yang efektif. Di bab ini, kita sudah belajar membedakan syntax error (masalah pada struktur kode) dan runtime exception (masalah saat eksekusi), mengenali jenis exception yang umum dan apa yang ditunjukkannya, membaca dan menafsirkan traceback detail untuk menemukan akar masalah, memahami bagaimana exception mengubah alur program dengan merambat naik pada call stack, dan membangun mindset debugging yang memperlakukan error sebagai informasi berharga alih-alih kegagalan.

Skill ini menjadi fondasi untuk bab berikutnya, di mana kita akan belajar menangani exception dengan baik menggunakan blok try dan except, sehingga program kita bisa pulih dari error dan tetap berjalan. Namun sebelum kita bisa menangani exception secara efektif, kita perlu memahaminya secara menyeluruh—dan itulah yang sudah kita lakukan di sini.

© 2025. Primesoft Co., Ltd.
support@primesoft.ai