Kursus
Saat kode Python mengalami masalah saat runtime, sering kali ia menimbulkan exception. Jika tidak ditangani, exception akan membuat program Anda crash. Namun, dengan blok try-except, Anda dapat menangkapnya, memulihkan dengan baik, dan menjaga aplikasi tetap berjalan.
Tutorial ini bukan membahas dasar-dasar exception, itu sudah kami bahas di panduan Exception & Error Handling in Python. Sebaliknya, di sini kita akan menyelami try-except dalam praktik: cara menyusun blok, menghindari kesalahan umum, dan menerapkan praktik terbaik yang membuat kode Anda lebih andal di skenario dunia nyata.
Pada akhirnya, Anda tidak hanya akan memahami bagaimana try-except bekerja, tetapi juga bagaimana menggunakannya secara Pythonic; menulis kode penanganan error yang jelas, mudah dirawat, dan siap produksi.
Jika Anda masih dalam perjalanan belajar Python, saya sarankan melihat jalur keterampilan Python Programming Fundamentals, yang akan membantu Anda membangun semua keterampilan esensial.
Mengapa Fokus pada try-except?
Penanganan error di Python pada dasarnya adalah tentang merancang program yang dapat menghadapi hal tak terduga. Dan meskipun ada banyak alat untuk menangani error, try-except adalah tulang punggung pendekatan Python.
Mengapa ini begitu penting?
- Ini mencerminkan filosofi Python. Di Python, gaya yang umum adalah EAFP; Easier to Ask Forgiveness than Permission. Alih-alih memeriksa semuanya di awal (apakah file ini ada? apakah input ini valid? apakah server tersedia?), Anda langsung mencoba operasinya. Jika gagal, Anda menangkap exception dan menanganinya. Ini menghasilkan kode yang lebih singkat dan bersih.
- Ini menjaga kode tetap berjalan di lingkungan dunia nyata. Input pengguna akan berantakan, file akan hilang, API akan gagal, dan jaringan akan terputus. Dengan
try-except, Anda dapat menulis kode yang tidak ambruk pada masalah pertama tetapi justru bereaksi dengan cerdas. - Cukup fleksibel untuk pemula maupun profesional. Pemula mungkin menggunakan
try-exceptuntuk menangkapValueErrorsaat mengonversi input ke integer. Sistem produksi mungkin menggunakannya untuk mencatat error, mencoba ulang operasi yang gagal, atau menimbulkan exception kustom yang memudahkan debugging.
Itulah mengapa artikel ini menyoroti try-except. Menguasainya adalah perbedaan antara menulis skrip yang hanya bekerja dalam kondisi sempurna dan menulis perangkat lunak yang tangguh, mudah dirawat, dan siap produksi.
Anatomi Blok Try‑Except
Dalam bentuk paling sederhana:
try:
risky_thing()
except SomeError:
handle_it()
Saat Python menemui error di dalam blok try, ia akan melompat ke blok except yang cocok alih-alih membuat program crash.
Anda juga dapat memperluas pola ini dengan klausa else dan finally:
try:
do_something()
except ValueError:
print("Bad value!")
else:
print("All good.")
finally:
clean_up()
Berikut contoh sederhana yang berfungsi:
try:
x = int(input("Enter a number: "))
except ValueError:
print("That wasn’t a number.")
else:
print("You entered", x)
finally:
print("Done.")
Blok except menangani error, else hanya berjalan jika semuanya berhasil, dan finally selalu berjalan, bahkan jika Anda menekan Ctrl‑C atau keluar.
Anda dapat menguasai dasar-dasar penanganan input pengguna di Python, dari prompt dasar hingga validasi lanjutan dan teknik penanganan error melalui tutorial Python User Input: Handling, Validation, and Best Practices kami.
Menangani Banyak Exception
Terkadang, satu except saja tidak cukup. Jalur kode yang berbeda dapat gagal dengan cara berbeda, dan menangkap semuanya dengan bare except: jelas tidak membantu; ini bisa menyembunyikan bug dan membuat debugging menjadi sakit kepala.
Misalnya Anda mencoba mengonversi sesuatu menjadi integer lalu membaginya. Berikut contoh yang tidak boleh dilakukan:
try:
result = int(user_input) / 2
except:
print("Something went wrong.")
Ini menangkap semuanya, termasuk hal yang mungkin tidak ingin Anda sembunyikan, seperti salah ketik pada nama variabel atau exception tak terduga yang mengarah ke masalah nyata.
Sebaliknya, jadilah spesifik:
try:
result = int(user_input) / 2
except ValueError:
print("That wasn't a number.")
except ZeroDivisionError:
print("Division by zero?")
Jika Anda memiliki beberapa tipe exception yang perlu diperlakukan sama, Anda dapat mengelompokkannya seperti ini:
try:
result = some_function()
except (TypeError, ValueError):
print("Something was wrong with the data.")
Dengan cara ini, Anda tetap jelas tentang apa yang mungkin salah, tanpa menduplikasi blok yang sama berulang kali.
Ada juga except Exception, yang lebih baik daripada bare except, tetapi masih terlalu luas. Lebih baik Anda membidik error spesifik yang Anda harapkan.
Menggunakan Blok else dan finally
Ketika kode di dalam blok try berhasil dan tidak ada exception yang ditimbulkan, Python mengeksekusi blok else.
try:
user_id = get_user_id()
except LookupError:
print("User not found.")
else:
print("Welcome, user", user_id)
Ini membantu Anda memisahkan logika penanganan exception dari jalur utama yang sukses, sehingga lebih mudah dibaca.
Lalu ada finally. Ia tidak peduli apa yang terjadi; ia akan berjalan apa pun yang terjadi. Ada exception? Tetap jalan. Tidak ada exception? Tetap jalan. Program crash karena Ctrl‑C? Tetap jalan. Sangat bagus untuk urusan pembersihan:
try:
f = open("data.txt")
process(f)
except IOError:
print("Couldn’t open file.")
finally:
f.close()
Ingat, jika file tidak pernah terbuka, f mungkin bahkan tidak ada, jadi berhati-hatilah. Anda bisa menggunakan context manager Python (with open(...) as f:) saat bekerja dengan file. Itu lebih aman.
Jika Anda ingin mempelajari teknik kunci, seperti penanganan exception dan pencegahan error, untuk menangani exception KeyError di Python secara efektif, saya sarankan tutorial Python KeyError Exceptions and How to Fix Them kami.
Praktik Terbaik try-except Python dan Jebakan Umum
Jujur saja: menulis blok try‑except itu semacam seni. Jika dilakukan dengan baik, mereka mencegah program Anda crash. Jika buruk, mereka mengubur bug begitu dalam hingga Anda tak akan menyadarinya sampai aplikasi Anda crash dan pengguna mengeluh.
Berikut kebiasaan yang layak dibangun:
Jaga blok try tetap ramping. Jangan membungkus seratus baris kode dalam satu try. Itu hanya membuat lebih sulit mengetahui apa yang menyebabkan masalah. Sebaliknya, bungkus hanya kode yang mungkin gagal:
# Good
try:
value = int(data)
except ValueError:
print("Couldn’t convert.")
# Bad
try:
# Tons of unrelated logic
value = int(data)
do_more()
something_else()
except ValueError:
print("Huh?")
Hindari memeriksa kondisi sebelum melakukan tindakan jika lebih mudah langsung mencoba dan menangkap error. Python punya nama untuk ini: EAFP, Easier to Ask Forgiveness than Permission. Jika Anda memeriksa apakah file ada lalu membukanya, Anda membuat race condition. Sebagai gantinya:
try:
with open("file.txt") as f:
content = f.read()
except FileNotFoundError:
print("No file.")
Pola ini menghindari masalah umum ketika file mungkin menghilang antara pengecekan dan pemanggilan open. Cukup coba saja. Jika gagal, tangkap kegagalannya.
Juga, hindari membisukan error dengan menangkap semuanya dan tidak melakukan apa-apa. Jangan lakukan ini:
try:
something()
except:
pass
Kecuali Anda benar-benar tahu apa yang Anda lakukan, ini tempat bug bersembunyi dan berkembang biak. Jika Anda harus membisukan, jadilah spesifik:
try:
something()
except TimeoutError:
# okay to ignore in this case
pass
Dan catat error di suatu tempat. Menelannya sepenuhnya berarti Anda di masa depan tidak akan tahu apa yang salah.
Exception Bawaan vs Kustom
Python hadir dengan banyak exception bawaan, dan itu mencakup banyak kasus. Anda mungkin sudah pernah menjumpai beberapa di antaranya:
ValueError: ketika sesuatu memiliki tipe yang benar tetapi nilainya tidak valid, sepertiint("hello").TypeError: ketika Anda mencoba menggunakan operasi pada tipe yang salah, seperti menambahkan string dan angka.ZeroDivisionError: ya, membagi dengan nol.FileNotFoundError: mencoba membuka file yang tidak ada.KeyError: ketika kunci tidak ada di dictionary.
Ini berguna, dan di sebagian besar skrip atau aplikasi, sudah lebih dari cukup. Namun terkadang Anda ingin menimbulkan sesuatu yang lebih deskriptif, yang masuk akal di dunia proyek Anda, bukan hanya dunia Python.
Misalkan Anda menulis aplikasi yang memproses pesanan online, dan Anda ingin menimbulkan error ketika pengguna mencoba membeli sesuatu yang stoknya habis. Anda bisa saja menggunakan ValueError, tetapi itu agak umum. Itu tidak memberi tahu orang berikutnya yang membaca kode Anda apa yang terjadi.
Di sinilah exception kustom bersinar.
class OutOfStockError(Exception):
pass
def check_inventory(product_id):
if not in_stock(product_id):
raise OutOfStockError(f"Product {product_id} is out of stock.")
Dengan membuat exception kustom, Anda menambah lapisan makna. Anda juga memberi diri Anda lebih banyak kontrol; Anda dapat menangkap situasi spesifik ini saja:
try:
check_inventory("shirt-001")
except OutOfStockError:
print("Sorry, that item is sold out.")
Ini hal kecil, tetapi membuat kode Anda lebih mudah dipahami dan dirawat, terutama di proyek besar. Dan ini selaras dengan pencatatan dan pemantauan; nama exception kustom jauh lebih mudah dicari daripada ValueError yang samar.
Logging, Melempar Ulang, dan Exception Chaining
Ada momen saat debugging: Anda melihat traceback, menatapnya, dan menyadari Anda tidak punya petunjuk mengapa sesuatu gagal. Di situlah logging berperan. Ini bukan sekadar mencatat error, tetapi memberi petunjuk bagi Anda (atau tim Anda) di masa depan untuk mengetahui apa yang salah.
Misalkan Anda menangkap sebuah exception dan ingin mencatatnya sebelum melanjutkan:
import logging
logging.basicConfig(level=logging.ERROR)
try:
do_something()
except ValueError as e:
logging.error("Failed to do something: %s", e)
raise
Perintah raise di akhir itu penting, ia melempar kembali exception yang sama setelah mencatatnya. Tanpanya, Anda justru menelan error. Terkadang itu baik-baik saja, tetapi biasanya tidak.
Lalu ada trik raise from. Ini untuk saat Anda menangani satu error tetapi perlu menimbulkan error lain, dan Anda tidak ingin kehilangan yang asli. Python memungkinkan Anda merangkainya:
try:
connect_to_database()
except TimeoutError as e:
raise ConnectionError("Database unavailable.") from e
Dengan cara ini, traceback menceritakan keseluruhan cerita. Anda mendapatkan ConnectionError yang baru, tetapi Anda juga melihat TimeoutError yang menyebabkannya.
Anda juga bisa menekan error asli (yang biasanya tidak disarankan) seperti ini:
raise ConnectionError("Just this error, nothing else.") from None
Namun kecuali Anda punya alasan kuat, mempertahankan rantai lengkap membantu semua orang memahami apa yang salah dan bagaimana efek runtunnya.
Anda dapat mempelajari dasar-dasar logging di Python dari Tutorial Logging in Python kami.
Contoh dan Use Case Dunia Nyata
Membahas penanganan exception secara abstrak itu satu hal, tetapi semuanya klik saat Anda melihatnya dalam kode sebenarnya.
Ambil contoh input pengguna. Tanyakan pada siapa pun yang pernah membangun alat command line atau validator form: pengguna akan memasukkan hal-hal paling aneh. Anda meminta angka? Seseorang akan mengetik “twelve.” Atau menempelkan nomor telepon. Atau hanya menekan Enter. Itu terjadi.
Alih-alih menulis daftar panjang pengecekan “bagaimana jika”, Anda bisa melakukan ini:
while True:
user_input = input("Enter a number: ")
try:
number = int(user_input)
break
except ValueError:
print("Try again with a whole number.")
Kode ini tidak panik saat mendapat input sampah. Ia memberi tahu pengguna untuk mencoba lagi dan berulang sampai semuanya terlihat baik. Jauh lebih bersih daripada menumpuk pernyataan if untuk setiap edge case.
Berikut contoh lain: membaca file yang mungkin tidak ada.
try:
with open("config.json") as f:
settings = f.read()
except FileNotFoundError:
print("Missing config file. Using defaults.")
settings = "{}"
Tidak perlu mengecek apakah file ada. Cukup coba buka, dan jika gagal, lanjutkan. Jika Anda mencoba mengecek sebelumnya (os.path.exists()), orang lain mungkin menghapus file itu di antara pengecekan dan pemanggilan open. Itu adalah race condition, bukan sesuatu yang ingin Anda debug.
Permintaan jaringan adalah ladang emas lain untuk exception. Anda tidak selalu bisa mempercayai internet untuk bersikap baik. Server down. Koneksi putus. DNS gagal. Jadi jika Anda melakukan sesuatu seperti ini:
import requests
try:
response = requests.get("https://example.com/data")
response.raise_for_status()
except requests.exceptions.RequestException as e:
print("Network problem:", e)
Kelas dasar RequestException dengan mudah menangkap hampir semua yang mungkin ditimbulkan requests, dari timeout hingga respons buruk. Anda tidak perlu menulis sepuluh blok except berbeda kecuali Anda ingin menanganinya secara berbeda.
Dan jika Anda menulis skrip otomatisasi atau layanan backend, membungkus logika kunci dalam blok try‑except bisa menjadi pembeda antara satu tugas yang gagal dan seluruh sistem yang padam. Anda ingin error dicatat, tugas yang dapat dipulihkan dicoba ulang, dan yang tidak dapat dipulihkan dimatikan dengan rapi, bukan dengan stack trace samar yang bergulir tanpa henti di log Anda.
Pelajari tentang otomatisasi Python, termasuk konsep dasar, pustaka kunci, bekerja dengan data, penggunaan peningkatan AI, dan praktik terbaik dari tutorial Python Automation: A Complete Guide kami.
Penggunaan Lanjutan Try-except Python
Sejauh ini, Anda mungkin sudah melihat betapa fleksibelnya try‑except. Namun fleksibilitas punya dua sisi. Mudah sekali bergeser dari membantu menjadi ceroboh tanpa disengaja. Berikut cara tetap menjaga kendali.
Tangkap exception yang spesifik. Jika Anda tahu apa yang bisa salah, sebutkan namanya:
try:
result = int(data)
except ValueError:
# Only catches invalid numbers, not everything else under the sun
Hindari bare except:. Jangan lakukan ini kecuali Anda menangani sesuatu yang sangat khusus. Ini akan menangkap hal-hal seperti KeyboardInterrupt, SystemExit, dan hal lain yang mungkin tidak ingin Anda bisukan.
Gunakan else dan finally saat keduanya membuat kode lebih jelas. Jangan memaksakannya hanya karena ada. Jika jalur normal kode Anda terkubur di dalam try, mungkin pindahkan ke else.
Jaga blok try tetap kecil. Semakin banyak yang Anda masukkan, semakin sulit mengetahui baris mana yang menyebabkan error. Bungkus hanya bagian yang mungkin gagal.
Catat error saat diperlukan, terutama di produksi. Bahkan jika Anda tidak crash, mengetahui apa yang gagal (dan kapan) membuat debugging jauh lebih mudah nanti.
Exception kustom tidak wajib, tetapi membantu. Jika Anda punya masalah spesifik aplikasi, definisikan error Anda sendiri. Ini dapat membuat log lebih mudah dibaca dan kode Anda lebih mudah dipahami.
Satu hal lagi: jangan gunakan exception untuk kontrol alur kecuali tidak ada cara yang lebih baik. Godaan menulis logika seperti “coba ini; jika gagal, lakukan itu” memang ada, tetapi jika itu sesuatu yang Anda harapkan sering terjadi, mungkin ada cara yang lebih rapi.
Kesimpulan
Seperti yang saya jelaskan sepanjang artikel ini, penanganan exception bukan hanya soal menghindari crash. Ini tentang menulis kode yang mengantisipasi masalah, menanganinya tanpa drama, lalu terus berjalan, atau berhenti dengan cara yang masuk akal. Ini perbedaan antara pengguna yang mendapatkan pesan membantu dan yang dikembalikan ke terminal dengan traceback panjang yang sulit dibaca.
Saya sangat menyarankan untuk mempelajari lebih lanjut tentang exception, dengan beberapa latihan langsung, di bab Catching Exceptions in Python dari kursus OOP in Python kami.
Python try-except FAQs
Apa perbedaan antara error dan exception di Python?
Error biasanya mengacu pada masalah yang mencegah Python bahkan memulai kode Anda, seperti titik dua yang hilang atau salah ketik pada keyword. Ini adalah syntax error. Exception terjadi saat kode berjalan, seperti mencoba membagi dengan nol atau membuka file yang tidak ada. Exception dapat ditangkap dan ditangani sehingga program Anda tidak crash.
Apakah buruk menggunakan bare except di Python?
Ya, dalam sebagian besar kasus. Bare except menangkap semuanya, termasuk hal-hal yang tidak Anda maksud untuk ditangkap, seperti interupsi keyboard atau sinyal keluar sistem. Itu membuat debugging sulit. Lebih baik menangkap exception spesifik, seperti ValueError atau FileNotFoundError, sehingga Anda tahu persis apa yang Anda tangani.
Kapan saya harus menggunakan else dalam blok try-except?
Gunakan else saat Anda ingin menjalankan kode hanya jika tidak ada exception yang terjadi di blok try. Ini membantu memisahkan logika jalur sukses dari logika penanganan error, yang dapat membuat kode Anda lebih mudah dibaca dan dirawat.
Apa gunanya finally jika saya sudah memiliki blok except?
finally berjalan apa pun yang terjadi, apakah ada error atau tidak. Ini sempurna untuk pembersihan: menutup file, melepaskan resource, membatalkan transaksi, dan sebagainya. Bahkan jika terjadi error atau Anda keluar lebih awal, finally tetap akan berjalan.
Haruskah saya selalu menggunakan `try-except` daripada mengecek kondisi terlebih dahulu?
Tidak selalu, tetapi sering kali lebih baik langsung try sesuatu dan catch error jika gagal. Pengembang Python menyebut ini EAFP, “Easier to Ask Forgiveness than Permission.” Ini lebih cepat dan menghindari bug tertentu, terutama ketika sesuatu dapat berubah antara pengecekan dan tindakan (seperti file yang dihapus).
