Belajar Python : Error dan Exception Handling Pada Python

Estimated: 10 min read
Belajar Python : Error dan Exception Handling Pada Python

Ketika kita membuat sebuah program menggunakan bahasa pemrograman ada kemungkinan-kemungkinan yang menyebabkan kesalahan pada program kita yang berjalan.

Secara umum kesalahan yang terjadi dibagi menjadi dua berdasarkan kejadiannya:

  1. Syntax Errors (Kesalahan Sintaks) atau disebut juga dengan Parsing Erros
  2. Exceptions (Pengecualian) atau disebut juga dengan Runtime Errors

Python sendiri telah menyediakan fitur yang sangat berguna untuk menangani dua kesalahan umum seperti di atas, yaitu:

  • Exception Handling
  • Assertions Exception

Assertions Exception merupakan sebuah peristiwa yang terjadi selama program berjalan yang mengganggu proses eksekusi sehingga terjadi error. Secara umum ketika python mengalami peristiwa yang tidak dapat diatasi maka hal tersebut dapat menimbulkan exception. Exception merupakan objek python yang mewakili dari kesalahan yang terjadi.

Kenapa kita perlu menghandle kesalahan yang terjadi???

Ketika python mengalami exception atau keadaan yang tidak dapat dihandle maka python akan berhenti mengeksekusi program saat itu juga. Bayangkan jika ada aplikasi kasir yang menggunakan python, ketika petugas kasir salah memasukkan nominal yang seharusnya berupa angka 1000 tetapi malah memasukkan 1ooo, python tidak mengenali dan menghandle inputan yang dimasukkan oleh petugas kasir maka aplikasi kasir tersebut akan error dan tidak dapat digunakan. Kita tidak ingin aplikasi yang kita buat berakhir seperti itu bukan???

Seharusnya ketika petugas kasir tersebut memasukkan inputan yang salah aplikasi akan memberi tahu bahwa nominal yang dimasukkan adalah salah.

"Nominal yang kamu masukkan bukan berupa angka, coba lagi."

Untuk itu kita perlu menangani exception atau kesalahan yang terjadi selama python mengeksekusi program.

1. Syntax Errors (Kesalahan Sintaks)

Kesalahan sintaks (syntax errors) sangat wajar dan umum terjadi ketika kita baru pertama kali belajar bahasa pemrograman Python. Kesalahan sintaks bisa terjadi karena ada kesalahan indentasi, typo pada saat menulis baris kode atau juga karena ada karakter yang kelupaan untuk kita tulis.

if 1 > 2 :
print("1 lebih besar dari 2")

Dari contoh baris code di atas maka python akan mengalami error IndentationError, karena tidak memberikan indentasi pada baris kedua:

  File "main.py", line 2
    print("1 lebih besar dari 2")
    ^
IndentationError: expected an indented block
if 1 > 2
  print("1 lebih besar dari 2")

Dari baris code di atas juga akan menghasilkan error SyntaxError, karena kita lupa menuliskan tanda : setelah 1 > 2.

  File "main.py", line 1
    if 1 > 2
           ^
SyntaxError: invalid syntax

Dari contoh-contoh syntax errors di atas kita dapat melihat bahwa Python telah memberi tahu kita dimana letak kesalahan yang terjadi. Python memberikan tanda ^ untuk memberi tahu kita dimana letak kesalahannya. Python juga menyertakan nama file dan nomor barisnya.

Selain itu Python juga memberi tahu kita tipe kesalahan yang terjadi. Pada contoh pertama Python memberi tahu kita bahwa telah terjadi kesalahan dengan tipe IndentationError dan pada contoh kedua kesalahannya adalah SyntaxError. Selanjutnya detail kesalahan diberi tahu setelah tipe kesalahan, untuk masing-masing contoh pertama dan kedua detail kesalahannya adalah expected an indented block dan invalid syntax.

2. Exceptions (Pengecualian)

Walaupun kita sudah memastikan semua baris code yang telah kita tulis tidak ada kesalahan (typo) dari segi penulisan, namun hal tersebut tidak dapat menjamin bahwa program kita bebas dari error. Bisa jadi ada kesalahan ketika program tersebut di eksekusi seperti contoh kasus petugas kasir dia atas. Kesalahan yang terjadi pada saat eksekusi sedang berjalan disebut dengan runtime errors atau exception. Exception harus dihandle agar program tidak langsung berhenti mengeksekusi ketika terjadi error.

def sum(nominal):
  global total
  total += float(nominal)

price = input("Masukkan Harga: ")
sum(price)
print("Total Harga : {0}".format(total))

Contoh di atas kita akan menerima inputan dari user. Kemudian inputan tersebut akan ditambahkan dengan variable total. Baris code di atas akan mengalami exception seperti berikut ketika dijalankan.

Masukkan Harga: 1000
Traceback (most recent call last):
  File "main.py", line 7, in <module>
    sum(price)
  File "main.py", line 4, in sum
    total += float(nominal)
NameError: name 'total' is not defined

Kalau dilihat program sempat berjalan dan meminta user untuk memasukkan harga, namun ketika dieksekusi program mengalami error seperti di atas. Dari error di atas dapat kita lihat bahwa telah terjadi exception dengan tipe NameError dengan keterangan name 'total' is not defined, hal ini terjadi karena variabel total belum kita definisikan secara global.

Mari kita coba definisikan variable total secara global.

total = 0
def sum(nominal):
  global total
  total += float(nominal)

price = input("Masukkan Harga: ")
sum(price)
print("Total Harga : {0}".format(total))

Eitss masih ada kemungkinan terjadi exception loh. Berikut exception yang terjadi jika user memasukkan inputan yang bukan merupakan angka.

Masukkan Harga: seribu
Traceback (most recent call last):
  File "main.py", line 7, in <module>
    sum(price)
  File "main.py", line 4, in sum
    total += float(nominal)
ValueError: could not convert string to float: 'seribu'

Exception yang terjadi sekarang adalah ValueError dengan detail could not convert string to float: 'seribu'. Hal ini terjadi karena inputan yang dimasukkan oleh user bukanlah angka, dan program python kita tidak menghandle hal tersebut. Sehingga keadaan yang tidak dapat ditangani oleh Python tersebut akan menghasilkan exception. Exception di atas terjadi saat kita mencoba mengubah inputan dari user menjadi sebuah bilangan angka, tetapi ketika yang diberikan oleh user bukan merupakan angka maka program kita akan mengalami error dan berhenti.

Seperti halnya pada syntax errors ketika terjadi Exception Python juga memberi tahu kita dibagian mana letak kesalahan yang menyebabkan terjadinya exception tersebut.

Ketika ingin menghandle exception yang terjadi, kita harus tau nama tipe exceptionnya. Python telah menyediakan Built-in Exception yang mungkin saja akan terjadi selama baris kode Python dieksekusi. Kalian dapat membacanya lebih detail di dokumentasi resmi python terkait Exception.

3. Exceptions Handling

Seperti yang telah kita ketahui bahwa exception dapat menyebabkan Python mengeksekusi program kita, maka dari itu kita perlu menghandle exception yang terjadi. Kita dapat menghandle exception berdasarkan tipe exception yang kita inginkan.

Exception handling pada Python menggunakan sintaks try dan except. Adapun bentuk lengkap untuk menghandle exception pada Python seperti berikut:

try:
    # baris kode yang ingin dijalankan
except:
    # baris kode yang ingin dijalankan
    # jika TERJADI Exception
else:
    # baris kode yang akan dijalankan
    # jika TIDAK TERJADI Exception
finally:
    # baris kode yang akan selalu dijalankan
    # di akhir baik ketika TERJADI atau
    # TIDAK TERJADI Exception
    # baris ini akan selalu di eksekusi

Misalnya pada kasus di atas, exception akan terjadi ketika kita mencoba mengubah inputan user yang berupa str menjadi float. Kita akan coba menghandle exception tersebut kali ini agar program tidak menjadi error.

total = 0
def sum(nominal):
  global total
  try:
    total += float(nominal)
  except:
    print("Harga harus berupa angka")

price = input("Masukkan Harga: ")
sum(price)
print("Total Harga : {0}".format(total))

Kita kita coba jalankan baris kode di atas dan memasukkan seribu sebagai inputan maka sekarang tidak akan terjadi error lagi. Program akan memberi tahu kita bahwa harga yang dimasukkan user harus berupa angka dan program tidak menghentikan proses eksekusi yang sedang berjalan.

Masukkan Harga: seribu
Harga harus berupa angka
Total Harga : 0

Jika kita tidak menuliskan tipe exception setelah sintaks except maka Python akan menghandle semua exception yang terjadi. Tentu saja hal ini bukan best practice jika kita harus menjalankan baris kode sesuai dengan tipe exception yang terjadi.

Untuk itu kita perlu menjelaskan kepada Python tipe exception apa yang ingin kita handle, kita akan melihat contoh lainnya.

def division(a, b):
  try:
    print("{0} / {1} = {2}".format(a, b, a / b))
  except ZeroDivisionError:
    print("Tidak bisa membagi angka dengan 0")

division(1,0)

Kita membuat sebuah fungsi sederhana yang akan membagikan dua buah angka. Pada sintaks except kita menjelaskan bahwa kita hanya ingin menghandle ketika terjadi exception dengan tipe ZeroDivisionError. Jika exception ini terjadi maka kita akan memunculkan pesan bahwa angka tidak bisa dibagi dengan 0.

Pada contoh di atas kita mencoba membagi 1 dengan 0, yang mana ketika kita jalankan maka program di atas akan memberikan output seperti berikut:

Tidak bisa membagi angka dengan 0

Bagaimana jika terjadi exception yang lain???

Jawabannya adalah program kita tidak akan menghandle exception tersebut dan akan terjadi error yang berakibat kode berhenti dieksekusi. Contohnya kita akan coba membagi 10 dengan '2'.

def division(a, b):
  try:
    print("{0} / {1} = {2}".format(a, b, a / b))
  except ZeroDivisionError:
    print("Tidak bisa membagi angka dengan 0")

division(10,"2")

Yang mana 10 merupakan angka dan '2' merupakan string biasa. Maka program di atas akan terjadi error seperti berikut.

Traceback (most recent call last):
  File "main.py", line 7, in <module>
    division(10, "2")    
  File "main.py", line 3, in division
    print("{0} / {1} = {2}".format(a, b, a / b))
TypeError: unsupported operand type(s) for /: 'int' and 'str'

Kita dapat menghandle exception sebanyak yang kita mau dan butuhkan. Kita akan coba memodifikasi kode di atas selain akan menghandle ZeroDivisionError program kita juga akan menghandle TypeError.

def division(a, b):
  try:
    print("{0} / {1} = {2}".format(a, b, a / b))
  except ZeroDivisionError:
    print("Tidak bisa membagi angka dengan 0")
  except Type:
    print("Inputan harus berupa angka")

division(10, "2")

Kita kita coba jalankan maka program akan memberi tahu kita jika inputan harus berupa angka yang valid.

Inputan harus berupa angka

Penggunakan blok else dan finally ketika menghandle exception bersifat opsional.

Kita akan melihat bagaimana dan kapan blok else dan finally dijalankan ketika menghandle exception.

def division(a, b):
  try:
    print("{0} / {1} = {2}".format(a, b, a / b))
  except ZeroDivisionError:
    print("Tidak bisa membagi angka dengan 0.")
  except TypeError:
    print("Inputan harus berupa angka.")
  else:
    print("Tidak ada exception yang terjadi.")
  finally:
    print("Program selesai dieksekusi.")

division(10, 2)

Ketika program di atas dijalankan maka akan mengeluarkan hasil seperti berikut:

10 / 2 = 5.0
Tidak ada exception yang terjadi.
Program selesai dieksekusi.

Karena tidak ada exception yang terjadi maka perintah di dalam blok else akan dijalankan yaitu menampilkan pesan Tidak ada exception yang terjadi.. Selanjutnya ketika semua selesai dijalankan maka Python akan mengeksekusi perintah yang ada di dalam blok finally yaitu menampilkan pesan Program selesai dieksekusi. Bagaimana jika ada exception yang terjadi??? Mari kita lihat.

Kita akan coba membagi 10 dengan '2' lagi seperti sebelumnya.

Inputan harus berupa angka.
Program selesai dieksekusi.

Seperti yang kita lihat di atas, Python akan mengeksekusi baris kode yang ada di dalam blok exception TypeError selanjutnya akan mengeksekusi baris kode yang ada di dalam blok finally. Perintah yang ada di dalam blok else hanya dijalankan ketika Tidak ada exception yang terjadi, sedangkan baris perintah yang ada di dalam blok finally akan selalu dijalankan ketika semuanya telah dieksekusi baik ketika terjadi exception ataupun tidak terjadi exception.

4. Membangkitkan Exceptions

Selain menghandle exceptions kita juga dapat membangkitkan atau membuat exception (raise exceptions) itu sendiri terjadi.

Mungkin terdengar aneh, untuk apa kita membangkitkan exception padahal kita sudah susah susah belajar exception handling yang digunakan justru untuk menangani ketika exception terjadi. Lah ini kenapa justru kita sendiri yang ingin membangkitkan dia ??? 🤔😫

Eitss, ketika kita membuat sebuah program yang kompleks terkadang kita perlu loh untuk membangkitkan exception ini. Oke kita akan melihat contoh sederhana untuk raise exception.

def validate_data(data):
  if "umur" not in data:
    raise KeyError("Data harus memiliki atribut umur")
  if not data.get("umur").isnumeric():
    raise ValueError("Umur harus berupa angka")

d = { "nama": "Depot Kode" }
validate_data(d)

Kita akan mencoba memvalidasi dictionary dengan fungsi validate_data(). Ketika dictionary yang diberikan tidak memiliki key umur maka program akan membangkitkan exception dengan tipe KeyError, selain itu program juga akan membangkitkan exception ValueError jika value dari umur bukan merupakan angka yang valid.

Ketika kita jalankan maka program di atas akan memberikan hasil seperti berikut:

Traceback (most recent call last):
  File "main.py", line 8, in <module>
    validate_data(d)
  File "main.py", line 3, in validate_data
    raise KeyError("Data harus memiliki atribut umur")
KeyError: 'Data harus memiliki atribut umur'

Kesimpulan

Error yang terjadi ketika kita membuat sebuah program adalah hal yang wajar dan sangat lumrah terjadi. Pada Python error dapat saja terjadi karena dua hal, bisa jadi error karena adalah kesalahan penulisan sintaks (Syntax Error) atau bisa juga terjadi error karena ada pengecualian ketika program di eksekusi (Runtime Error) atau yang biasa disebut Exceptions.

Ketika terjadi exception maka Python akan menghentikan proses eksekusi kode yang sedang berjalan, untuk menghindari program kita berhenti ketika dieksekusi oleh Python kita dapat menghandle exception yang terjadi (Exception handling).

Kita dapat menggunakan sintaks try dan except untuk menghandle exceptions. Kita juga dapat memberi tahu python bahwa kita hanya ingin menghandle exception tertentu saja dengan menuliskan tipe exception setelah sintaks except. Pastikan kita tahu exception apa saja yang mungkin terjadi untuk kita handle. Kalau kita tidak menuliskan tipe exceptionnya maka python akan menghandle semua exception yang terjadi secara default.

Selain menghandle exception, kita juga dapat mengbangkitkan exception itu sendiri (Raise Exceptions) dengan sintaks raise.

Comments

Mohon sertakan informasi yang detail saat bertanya tentang eror, seperti: pesan error, log, dan screenshot.