Sesi 14: Penanganan Kesalahan (Error Handling) & Debugging
Program Robust: Membangun pertahanan untuk menjaga program tetap berjalan (crash-proof) ketika menghadapi data yang tidak valid, file yang hilang, atau input yang tidak terduga.
I. Ulasan: Tipe Error dan Blok try-except
Ada tiga tipe kesalahan utama: Syntax Error (kesalahan tata bahasa, mudah diperbaiki), Runtime Error (program berhenti saat dieksekusi, misalnya ZeroDivisionError), dan Logical Error (program berjalan, tetapi hasilnya salah).
Tujuan try-except:
Blok try-except digunakan untuk "menangkap" Runtime Error dan memberikan respons yang anggun, mencegah program mati mendadak (crash). Ini sangat penting saat berhadapan dengan data dunia nyata yang tidak sempurna.
Komponen Error Handling:
- try: Blok kode yang berpotensi menimbulkan error diletakkan di sini.
- except [ErrorType]: Jika error terjadi di blok try, eksekusi melompat ke sini. Anda dapat menentukan tipe error spesifik (misalnya, ValueError).
- else (Opsional): Blok kode yang dieksekusi hanya jika blok try berhasil tanpa error.
- finally (Opsional): Blok kode yang selalu dieksekusi, terlepas dari apakah error terjadi atau tidak (sering dipakai untuk membersihkan sumber daya, misalnya menutup koneksi database atau berkas).
II. Contoh Manual: Menghindari Pembagian dengan Nol
Dalam Fisika, menghitung resistensi rata-rata dari paralel resistor sering melibatkan pembagian. Jika salah satu nilai resistensi diinput sebagai nol, program akan crash.
2.1. Formula Resistor: 1/Rtotal = 1/R1 + 1/R2 + ...
Langkah 1 (Loop): Coba hitung 1/Ri untuk setiap nilai R.
Langkah 2 (Error): Saat Ri = 0.0, Python akan mengeluarkan ZeroDivisionError.
Solusi: Tangkap error ini di blok except, dan berikan pesan yang jelas alih-alih membiarkan program berhenti.
III. Kode Praktik (Google Colab)
3.1. Kode Sederhana: Menangani ValueError (Input Numerik)
Memastikan input dari pengguna berupa angka (float) saat menghitung energi potensial.
def hitung_energi_aman():
while True:
try:
massa = input("Masukkan Massa (kg): ")
tinggi = input("Masukkan Tinggi (m): ")
# Coba konversi ke float (potensi ValueError)
m = float(massa)
h = float(tinggi)
# Hitung Energi Potensial (g=9.8)
Ep = m * 9.8 * h
print(f"\nEnergi Potensial: {Ep:.2f} Joule")
break # Keluar dari loop jika berhasil
except ValueError:
print("\n[ERROR] Input harus berupa angka valid. Coba lagi.")
except Exception as e:
# Menangkap error lain yang tidak terduga
print(f"[ERROR KRITIS] Terjadi kesalahan tak terduga: {e}")
# hitung_energi_aman() # Panggil fungsi untuk mencoba di Colab
3.2. Kode Kompleks: Menangani FileNotFoundError dan Data Rusak (CSV)
Integrasi try-except dengan File Handling untuk memproses data dari berkas yang mungkin hilang atau memiliki baris yang rusak.
import numpy as np
def proses_data_eksperimen(nama_berkas):
data_list = []
try:
# Coba membuka berkas (potensi FileNotFoundError)
with open(nama_berkas, 'r') as file:
print(f"Berhasil memuat berkas: {nama_berkas}")
is_header = True
for line in file:
if is_header:
is_header = False
continue
# Coba memproses setiap baris (potensi IndexError/ValueError)
try:
parts = line.strip().split(',')
nilai = float(parts[0]) # Anggap hanya ada satu kolom data
data_list.append(nilai)
except (IndexError, ValueError) as data_error:
print(f" [WARNING] Baris rusak/kosong dilewati: {line.strip()}")
# Jika berhasil, hitung mean
if data_list:
data_np = np.array(data_list)
print(f"\nAnalisis Berhasil: Rata-rata data = {np.mean(data_np):.2f}")
else:
print("\n[INFO] Berkas kosong atau semua baris rusak.")
except FileNotFoundError:
print(f"\n[ERROR KRITIS] Berkas '{nama_berkas}' tidak ditemukan. Cek path!")
except Exception as e:
print(f"\n[ERROR KRITIS UMUM] Kesalahan tak terduga: {e}")
# Contoh pemanggilan (Ganti nama berkas untuk simulasi error)
# proses_data_eksperimen('data_matriks.csv') # Berkas dari Sesi 13
# proses_data_eksperimen('berkas_hilang.csv') # Simulasi FileNotFoundError
IV. Dasar Debugging (Melacak Error Logika)
Debugging adalah proses menemukan dan menghilangkan bug (kesalahan logika). Berbeda dengan Error Handling yang menangani Runtime Error, debugging mengatasi Logical Error (kode berjalan tetapi hasilnya salah).
Strategi Debugging Dasar:
- Print Statement: Metode paling dasar. Sisipkan perintah print() strategis untuk melihat nilai variabel di titik eksekusi tertentu (misalnya, di dalam loop).
- Pemeriksaan Tipe: Jika hasil aneh, cek tipe data variabel menggunakan print(type(variabel)). Seringkali, operasi matematika gagal karena tipe data masih string.
- Pemeriksaan Batas (Boundary Check): Uji kode dengan nilai batas (nol, negatif, nilai sangat besar/kecil) untuk menemukan bug pada kondisi perulangan atau kondisional.
Contoh Debugging (Print Taktis)
Mengecek nilai iterasi yang salah dalam kalkulasi faktorial.
# Fungsi yang salah (Logical Error)
def hitung_faktorial_salah(n):
hasil = 1
# Seharusnya: range(1, n + 1)
for i in range(1, n):
# Tambahkan print untuk melacak nilai i dan hasil
print(f"[DEBUG] i={i}, hasil_sebelum={hasil}")
hasil *= i
return hasil
# print(hitung_faktorial_salah(4))
# Output salah: 6 (seharusnya 24). Debugging menunjukkan loop berhenti terlalu cepat.
V. Penugasan / PR Sesi 14: Kalkulator Resistensi Aman
Tugas Anda adalah membuat fungsi hitung_resistor_paralel() yang meminta dua nilai resistensi (R1 dan R2) dari pengguna, dan menghitung total resistensi paralel:
- try-except 1: Tangkap ValueError jika pengguna memasukkan input non-numerik.
- try-except 2: Tangkap ZeroDivisionError jika salah satu resistensi adalah 0, dan berikan pesan bahwa "Resistensi nol tidak valid dalam perhitungan paralel ini."
- Fungsi else: Cetak hasil total resistensi (Rtotal = 1 / (1/R1 + 1/R2)) hanya jika input valid.