BAB 10: Membaca Petunjuk Komputer: Galat dan Cara Menanganinya
Studi kasus: "Lima berkas kiriman tim lapangan" #
Tim lapangan mengirim lima berkas data. Anda menjalankan skrip pembaca, dan skrip berhenti di berkas ketiga dengan tulisan merah panjang. Dua berkas sisanya tidak sempat dibaca. Kepala Seksi bertanya: "Mengapa satu berkas rusak menghentikan semuanya?" Jawabannya: skrip Anda belum siap menghadapi galat. Bab ini mengajarkan cara membaca galat dan cara menanganinya dengan tenang.
Konsep: galat dalam tiga kalimat #
Galat (error) adalah pesan dari Python bahwa ia tidak bisa melanjutkan, lengkap dengan petunjuk letak dan sebabnya. Bayangkan petugas yang menolak berkas dengan catatan: "halaman 3, baris 5: tanda tangan kurang". Dengan try/except, Anda memberi petugas itu instruksi: "bila ada berkas bermasalah, catat lalu lanjutkan ke berkas berikutnya".

Istilah baru di bagian ini:
- Galat (exception): peristiwa yang menghentikan skrip.
- Traceback: tulisan jejak galat. Dibaca dari baris paling bawah ke atas.
trydanexcept: coba kerjakan, dan bila galat, tangkap lalu tangani.raise: perintah untuk menimbulkan galat sendiri dengan pesan yang jelas.assert: perintah memastikan sebuah syarat terpenuhi.
Membaca pesan galat #
Simpan tiga baris ini sebagai rata.py, lalu jalankan:
nilai = []
print("Menghitung rata-rata")
print(sum(nilai) / len(nilai))Python menampilkan:
Menghitung rata-rata
Traceback (most recent call last):
File "D:\Latihan\rata.py", line 3, in <module>
print(sum(nilai) / len(nilai))
~~~~~~~~~~~^~~~~~~~~~~~
ZeroDivisionError: division by zeroBaris pertama (Menghitung rata-rata) adalah hasil print sebelum galat. Alamat berkas di komputer Anda akan berbeda. Cara membacanya, dari bawah ke atas:
- Baris paling bawah menyebut jenis galat dan alasannya:
ZeroDivisionError: division by zero. Artinya: ada pembagian dengan nol. - Baris bergaris
~~~^~~~menandai bagian kode yang bermasalah, tepat di bawah baris penyebab:print(sum(nilai) / len(nilai)). - Baris
File ...menyebut nama berkas dan nomor baris: berkasrata.py, baris 3.
Kini Anda bisa langsung ke baris 3 dan bertanya: mengapa len(nilai) bernilai nol? Karena daftar nilai kosong.
Jenis galat yang paling sering muncul #
| Jenis galat | Contoh pesan | Penyebab umum |
|---|---|---|
IndexError | list index out of range | Nomor daftar melebihi isi |
KeyError | 'B' | Kunci kamus tidak ada |
NameError | name 'Nama' is not defined | Salah ketik atau huruf besar-kecil |
TypeError | can only concatenate str (not "float") to str | Mencampur teks dengan angka |
ValueError | invalid literal for int() with base 10: 'empat' | Isi tidak bisa diubah ke jenis yang diminta |
FileNotFoundError | No such file or directory | Alamat berkas salah |
ModuleNotFoundError | No module named 'qgis' | Modul belum terpasang atau salah penjalan |
IndentationError | expected an indented block | Jarak menjorok salah |
ZeroDivisionError | division by zero | Pembagi bernilai nol |
Menangani galat: try dan except #
def persen(bagian, total):
try:
return 100 * bagian / total
except ZeroDivisionError:
return None
print("Persen 3 dari 12:", persen(3, 12))
print("Persen 3 dari 0:", persen(3, 0))Penjelasannya:
- Python mencoba isi
trylebih dulu. - Bila tidak ada galat, hasil dikembalikan seperti biasa.
- Bila terjadi
ZeroDivisionError, Python melompat ke blokexceptyang cocok. Di sini jawabannyaNone, artinya "tidak ada jawaban yang masuk akal". - Skrip tidak berhenti. Baris
printberikutnya tetap berjalan.
Persen 3 dari 12: 25.0
Persen 3 dari 0: NoneBlok lengkapnya punya empat bagian:
try: yang dicoba.except JenisGalat: ditangani bila galat itu muncul. Boleh ada beberapaexcept.else: berjalan hanya bila tidak ada galat.finally: selalu berjalan, galat atau tidak. Cocok untuk merapikan.
Menimbulkan galat sendiri: raise dan assert #
def luas_ke_hektar(m2):
if m2 < 0:
raise ValueError("luas tidak boleh negatif: " + str(m2))
return m2 / 10000
try:
luas_ke_hektar(-5)
except ValueError as e:
print("Galat tertangkap:", e)
luas = 3
assert luas > 0, "luas harus positif"
print("lolos")Penjelasannya:
raise ValueError("...")menghentikan fungsi dengan pesan buatan Anda yang jelas.except ValueError as emenangkap galat itu, daneberisi pesannya.assert syarat, "pesan"memastikan syarat benar. Bila salah, skrip berhenti denganAssertionErrordan pesan Anda.
Galat tertangkap: luas tidak boleh negatif: -5
lolosSkrip yang dibedah: memeriksa masukan sebelum dipakai #
Tujuan. Membuka empat berkas kiriman lapangan satu per satu. Berkas yang bermasalah dilewati dengan pesan yang jelas, dan berkas yang baik tetap dibaca.
Bahan. Paket data paket-i4, folder Kiriman_Lapangan berisi tim_a.gpkg (baik), tim_e.gpkg (rusak), dan tim_f.gpkg (kolom Kondisi tidak ada). Berkas tim_x.gpkg memang tidak ada. Ganti dua baris awal DATA dan HASIL sesuai komputer Anda. Dijalankan di Konsol atau Editor QGIS.
Skrip utuh:
# [SKRIP 4.1: Memeriksa masukan sebelum dipakai dan menangkap galat dengan try-except]
# Penulis: Badar Mubarok Yogaswara
import os
from qgis.core import QgsVectorLayer
DATA = "D:/Latihan/paket-i4"
HASIL = "D:/Latihan/hasil_i4"
def muat_vektor(jalur, nama, field_wajib=()):
"""Membuka layer vektor. Bila ada yang tidak beres, berhenti dengan pesan yang jelas."""
if not os.path.exists(jalur):
raise FileNotFoundError("berkas tidak ada: " + jalur)
layer = QgsVectorLayer(jalur, nama, "ogr")
if not layer.isValid():
raise ValueError("berkas tidak bisa dibuka (mungkin rusak): " + os.path.basename(jalur))
kurang = [f for f in field_wajib if layer.fields().indexOf(f) < 0]
if kurang:
raise ValueError("field wajib tidak ada: " + ", ".join(kurang))
if layer.featureCount() == 0:
raise ValueError("layer kosong, tidak ada fitur")
return layer
# Empat berkas dicoba satu per satu. Satu gagal tidak boleh menghentikan yang lain.
kasus = [
DATA + "/Kiriman_Lapangan/tim_a.gpkg", # baik
DATA + "/Kiriman_Lapangan/tim_x.gpkg", # tidak ada
DATA + "/Kiriman_Lapangan/tim_e.gpkg", # rusak
DATA + "/Kiriman_Lapangan/tim_f.gpkg", # field Kondisi tidak ada
]
for jalur in kasus:
nama = os.path.basename(jalur)
try:
layer = muat_vektor(jalur, nama, field_wajib=["Kondisi", "Tinggi_Phn"])
except FileNotFoundError as e:
print("[LEWATI] %s -> %s" % (nama, e))
except ValueError as e:
print("[LEWATI] %s -> %s" % (nama, e))
else:
# blok else: hanya jalan bila TIDAK ada galat
print("[OK] %s -> %d fitur" % (nama, layer.featureCount()))
finally:
# blok finally: selalu jalan, berhasil atau gagal
print(" selesai memeriksa", nama)
# Galat hitungan yang sering terjadi: pembagian dengan nol
def persen(bagian, total):
try:
return 100 * bagian / total
except ZeroDivisionError:
return None # tidak ada jawaban yang masuk akal
print("Persen 3 dari 12:", persen(3, 12))
print("Persen 3 dari 0:", persen(3, 0))Penjelasan baris demi baris. Skrip ini panjang, jadi dibahas dalam empat blok. Nomor baris mengikuti skrip di atas.
Blok 1: pembuka (baris 1-7).
| Baris | Tulisan | Artinya |
|---|---|---|
| 1-2 | # [SKRIP 4.1 ... | Judul dan nama penulis. |
| 3-4 | import os, from qgis.core import QgsVectorLayer | Buka perkakas sistem dan perkakas pembuka layer vektor. |
| 6-7 | DATA = ..., HASIL = ... | Dua alamat di satu tempat (Bab 8). Ganti sesuai komputer Anda. |
Blok 2: fungsi penjaga muat_vektor (baris 10-22). Fungsi ini memeriksa empat hal secara berurutan. Begitu satu pemeriksaan gagal, ia menimbulkan galat dengan pesan yang jelas, dan berhenti.
| Baris | Tulisan | Artinya |
|---|---|---|
| 10 | def muat_vektor(jalur, nama, field_wajib=()): | Buat fungsi dengan tiga bahan. Bahan ketiga boleh dikosongkan karena punya nilai bawaan: tuple kosong. |
| 11 | """Membuka layer ...""" | Docstring: catatan penjelasan fungsi (Bab 7). |
| 12-13 | if not os.path.exists(jalur): raise FileNotFoundError(...) | Pemeriksaan 1: berkas harus ada. Bila tidak, timbulkan galat jenis FileNotFoundError dengan pesan buatan sendiri. |
| 14-16 | layer = QgsVectorLayer(...) lalu if not layer.isValid(): raise ValueError(...) | Pemeriksaan 2: berkas harus bisa dibuka. Berkas rusak menghasilkan layer tidak valid. |
| 17-19 | kurang = [... for f in field_wajib if ... < 0] lalu raise | Pemeriksaan 3: semua kolom wajib harus ada. Comprehension (Bab 6) mengumpulkan kolom yang hilang. indexOf memberi -1 bila kolom tidak ada. |
| 20-21 | if layer.featureCount() == 0: raise ... | Pemeriksaan 4: layer tidak boleh kosong. |
| 22 | return layer | Semua lolos, kembalikan layernya. |
Blok 3: perulangan dengan try (baris 25-45).
| Baris | Tulisan | Artinya |
|---|---|---|
| 25-31 | kasus = [...] | Daftar empat alamat berkas yang akan dicoba. Komentar menandai kondisi masing-masing. |
| 32-33 | for jalur in kasus: lalu nama = os.path.basename(jalur) | Ulangi tiap alamat. Ambil nama berkasnya saja. |
| 34-35 | try: layer = muat_vektor(...) | Coba buka berkas dengan fungsi penjaga. Kolom wajib: Kondisi dan Tinggi_Phn. |
| 36-39 | except FileNotFoundError as e: dan except ValueError as e: | Dua jenis galat ditangani. Tiap kali, cetak pesan [LEWATI] dan lanjut ke berkas berikutnya. |
| 40-42 | else: | Berjalan hanya bila tidak ada galat: cetak [OK] dan jumlah fitur. |
| 43-45 | finally: | Selalu berjalan: cetak "selesai memeriksa". |
Blok 4: galat hitungan (baris 47-55). Fungsi persen memakai pola yang sama seperti contoh di awal bab. Ia mengembalikan None bila pembaginya nol.
Hasil. Jalankan dengan DATA menunjuk folder paket Anda. Hasil di komputer penulis (jalur pada baris [LEWATI] tim_x.gpkg mengikuti nilai DATA Anda):
[OK] tim_a.gpkg -> 6 fitur
selesai memeriksa tim_a.gpkg
[LEWATI] tim_x.gpkg -> berkas tidak ada: D:/Latihan/paket-i4/Kiriman_Lapangan/tim_x.gpkg
selesai memeriksa tim_x.gpkg
[LEWATI] tim_e.gpkg -> berkas tidak bisa dibuka (mungkin rusak): tim_e.gpkg
selesai memeriksa tim_e.gpkg
[LEWATI] tim_f.gpkg -> field wajib tidak ada: Kondisi
selesai memeriksa tim_f.gpkg
Persen 3 dari 12: 25.0
Persen 3 dari 0: NoneSatu berkas baik dan tiga berkas bermasalah, tetapi keempatnya diperiksa. Itulah tujuan try/except di dalam perulangan.
Bagian yang boleh diubah.
- Baris 6, lokasi data. Ganti dengan lokasi
paket-i4di komputer Anda. - Baris 26-31, daftar berkas. Ganti dengan berkas Anda sendiri.
- Baris 35, kolom wajib. Ganti nama kolom sesuai data Anda:
field_wajib=["KODE", "LUAS"]. - Isi pesan di
printdanraise. Ganti dengan kalimat yang paling jelas bagi rekan kerja Anda.
Jebakan.
- Urutan
except. Python memakaiexceptpertama yang cocok. Tulis galat yang spesifik di atas, dan yang umum di bawah. exceptkosong. Menulisexcept:tanpa jenis menangkap semuanya, termasuk salah ketik Anda sendiri, dan menyembunyikan masalah. Selalu sebut jenis galatnya.- Jalur contoh. Bila
DATAbelum diganti, semua berkas akan[LEWATI]dengan pesan "berkas tidak ada". Itu bukan kerusakan data. - Menyembunyikan terlalu banyak. Menangkap galat lalu diam saja membuat masalah baru tak terlihat. Selalu cetak atau catat sesuatu.
Latihan variasi. Tambahkan satu berkas ke daftar kasus, yaitu tim_c.gpkg, lalu jalankan lagi. Apa hasilnya?
Jawabannya bergantung pada isi tim_c.gpkg. Pola yang Anda pelajari memberi tahu Anda cara mencari tahu: baca baris [OK] atau [LEWATI]. Bila [LEWATI], pesan setelah panah menyebut alasannya.
Cek paham #
- Pada pesan galat, baris mana yang dibaca pertama?
- Apa beda
elsedanfinallypada bloktry? - Mengapa
except:tanpa jenis galat tidak dianjurkan?
Jawaban.
- Baris paling bawah, yang menyebut jenis dan alasan galat.
elseberjalan hanya bila tidak ada galat.finallyselalu berjalan.- Karena menangkap semua galat, termasuk kesalahan tulis Anda sendiri, sehingga masalah tersembunyi.
Kesalahan umum #
- Panik melihat tulisan merah panjang. Perbaikan: baca baris paling bawah dulu, lalu naik.
- Menangkap galat tanpa mencetak apa pun. Perbaikan: selalu beri pesan, supaya Anda tahu apa yang dilewati.
- Membungkus seluruh skrip dalam satu
try. Perbaikan: bungkus hanya bagian yang memang bisa gagal, misalnya membuka berkas.
Ringkasan dan latihan #
- Baca galat dari bawah ke atas: jenis dan alasan, baris penyebab, nama berkas dan nomor baris.
try/except/else/finallymenangani galat tanpa menghentikan skrip.raisemenimbulkan galat dengan pesan sendiri.assertmemastikan sebuah syarat.
Latihan. Tulis fungsi rata_rata(daftar) yang mengembalikan None bila daftar kosong, dan rata-ratanya bila tidak. Uji dengan daftar kosong dan daftar berisi tiga angka.
Tabel perbandingan: empat bagian blok try #
| Bagian | Kapan berjalan | Kegunaan |
|---|---|---|
try | Selalu dicoba lebih dulu | Pekerjaan yang bisa gagal |
except | Hanya bila galat itu muncul | Menangani galat dan mencetak pesan |
else | Hanya bila tidak ada galat | Jalur sukses |
finally | Selalu | Merapikan, menutup, atau mencatat |