Exception Handling

Introduction

ဒီ chapter မှာတော့ program ပေါက်တာ၊ error တက်တာတွေကို ဘယ်လို handle လုပ်ရလဲဆိုတာကို တွေ့ရပါမယ်။

Real-world မှာ program တွေက အမြဲတမ်း မမျှော်လင့်တဲ့ အရာတွေနဲ့ ကြုံရတယ်:

  • User က နံပါတ် ထည့်ရမှာကို စာလုံး ထည့်တာ
  • File ဖတ်ချင်တာ file မရှိဘူး
  • Network connection ပြတ်သွားတာ
  • Zero နဲ့ စားမိတာ
  • Dictionary မှာ မရှိတဲ့ key ခေါ်တာ

အဲ့လို အရာတွေကို Exception (ချွင်းချက်) လို့ ခေါ်တယ်။ Exception Handling က program ပေါက်မသွားအောင်၊ ရပ်မသွားအောင် gracefully handle လုပ်ဖို့ပဲ။

Exception ဆိုတာ?

Exception ဆိုတာ program run နေတုန်း မထင်မှတ်ဘဲ ဖြစ်လာတဲ့ error တစ်ခု။

Without Exception Handling:

without_exception_handling.py
# User ကို နံပါတ် ထည့်ခိုင်းမယ် age = int(input("အသက် ထည့်ပါ: ")) print(f"bro အသက် {age} နှစ်") # User က "abc" ထည့်လိုက်ရင်? # ValueError: invalid literal for int() with base 10: 'abc' # Program ကသွားလိုက်မယ်!

With Exception Handling:

with_exception_handling.py
try: age = int(input("အသက် ထည့်ပါ: ")) print(f"bro အသက် {age} နှစ်") except ValueError: print("နံပါတ်ပဲ ထည့်ပါ bro!") # User က "abc" ထည့်လည်း error မတက်တော့ဘူး။ # သူ့ကို message လှလှလေး ပြပြီး ဆက်သွားမယ်
Exception Handling:
  • Program ပေါက်မသွားအောင် ကာကွယ်တာ၊ error တက်လည်း program မရပ်တော့ဘူး။
  • User ကို အဆင်ပြေတဲ့ error message ပြတာ
  • Cleanup operations (file close, connection close) လုပ်တာ
  • Program ကို stable ဖြစ်အောင် လုပ်တာ

Basic try-except

အရိုးရှင်းဆုံး exception handling structure က try-except ပေါ့။

Syntax:

try-except Syntax
try: # error ဖြစ်နိုင်တဲ့ code pass except ExceptionType: # error ဖြစ်ရင် လုပ်မယ့် code pass

Example 1: Division by Zero

division_error.py
try: result = 10 / 0 print(result) except ZeroDivisionError: print("သုညနဲ့ မစားနဲ့ bro!")

Example 2: Type Conversion Error

type_conversion_error.py
try: number = int("abc") print(number) except ValueError: print("စာလုံးကို နံပါတ် မပြောင်းလို့ရဘူး!")

Example 3: Getting Exception Details

exception_details.py
try: result = 10 / 0 except ZeroDivisionError as e: print(f"Error: {e}") print(f"Error type: {type(e)}")

Output:

Output
Error: division by zero Error type: <class 'ZeroDivisionError'>

The Complete Squad: try-except-else-finally

Exception handling ရဲ့ အပြည့်အစုံ structure မှာ အပိုင်း ၄ ပိုင်း ရှိတယ်။

Structure:

Complete Structure
try: # error ဖြစ်နိုင်တဲ့ code (စမ်းကြည့်မယ့် code) pass except ExceptionType: # error ဖြစ်ရင် run မယ် (error ဖမ်းမယ်) pass else: # error မဖြစ်ရင် run မယ် (အဆင်ပြေရင် run မယ်) pass finally: # error ဖြစ်ဖြစ် မဖြစ်ဖြစ် အမြဲ run မယ် (cleanup) pass

Detailed Explanation:

  • try: error ဖြစ်နိုင်တဲ့ code ကို စမ်းကြည့်တယ်
  • except: error ဖြစ်ရင် ဒီ block run မယ် (error အဖမ်းသမား)
  • else: error မဖြစ်ဘဲ အဆင်ပြေရင် ဒီ block run မယ် (အေးဆေးသမား)
  • finally: ဘာပဲဖြစ်ဖြစ် အမြဲ run မယ် (တာဝန်ကျေသမား - cleanup အတွက်)

Complete Example:

complete_example.py
try: print("1. try block: စမ်းကြည့်နေတယ်...") age = int(input("အသက် ထည့်ပါ: ")) result = 100 / age except ValueError: print("2. except block: နံပါတ်ပဲ ထည့်ပါ bro!") except ZeroDivisionError: print("2. except block: သုညနဲ့ မစားနဲ့!") else: print(f"3. else block: အဆင်ပြေတယ်! Result = {result}") finally: print("4. finally block: ဒါ အမြဲ run တယ်!")

Test Cases:

Test Case 1: Valid Input (20)
1. try block: စမ်းကြည့်နေတယ်... အသက် ထည့်ပါ: 20 3. else block: အဆင်ပြေတယ်! Result = 5.0 4. finally block: ဒါ အမြဲ run တယ်!
Test Case 2: Invalid Input (abc)
1. try block: စမ်းကြည့်နေတယ်... အသက် ထည့်ပါ: abc 2. except block: နံပါတ်ပဲ ထည့်ပါ bro! 4. finally block: ဒါ အမြဲ run တယ်!
Test Case 3: Zero Input (0)
1. try block: စမ်းကြည့်နေတယ်... အသက် ထည့်ပါ: 0 2. except block: သုညနဲ့ မစားနဲ့! 4. finally block: ဒါ အမြဲ run တယ်!

finally for File Handling:

finally_file_example.py
f = None try: f = open("data.txt", "r") content = f.read() print(content) except FileNotFoundError: print("File မရှိဘူး") finally: # error ဖြစ်ဖြစ် မဖြစ်ဖြစ် file ကို ပိတ်ရမယ် if f: f.close() print("File ပိတ်ပြီး")
Important:
  • else block က error မဖြစ်မှ run တယ်
  • finally block က ဘာပဲဖြစ်ဖြစ် အမြဲ run တယ်
  • finally ကို file close, connection close စတဲ့ cleanup အတွက် သုံးတယ်

Built-in Exceptions

Python မှာ ပါလာတဲ့ exception အမျိုးအစားတွေ အများကြီး ရှိတယ်။

Common Built-in Exceptions:

1. ValueError:

တန်ဖိုးက မှန်ပေမယ့် အမျိုးအစား မမှန်တာ

value_error_example.py
try: number = int("abc") # string ကို int မပြောင်းလို့ရဘူး except ValueError as e: print(f"ValueError: {e}") try: number = int("12.5") # decimal string ကို int မပြောင်းလို့ရဘူး except ValueError as e: print(f"ValueError: {e}")

2. TypeError:

မတူညီတဲ့ type တွေကို တွဲသုံးတာ

type_error_example.py
try: result = "Hello" + 5 # str နဲ့ int ပေါင်းလို့မရဘူး except TypeError as e: print(f"TypeError: {e}") try: result = len(123) # int မှာ length မရှိဘူး except TypeError as e: print(f"TypeError: {e}")

3. ZeroDivisionError:

သုညနဲ့ စားတာ

zero_division_example.py
try: result = 10 / 0 except ZeroDivisionError as e: print(f"ZeroDivisionError: {e}") try: result = 10 % 0 # modulo မှာလည်း error except ZeroDivisionError as e: print(f"ZeroDivisionError: {e}")

4. FileNotFoundError:

File ရှာမတွေ့တာ

file_not_found_example.py
try: with open("missing_file.txt", "r") as f: content = f.read() except FileNotFoundError as e: print(f"FileNotFoundError: {e}") print("File မရှိပါဘူး")

5. KeyError:

Dictionary မှာ မရှိတဲ့ key ခေါ်တာ

key_error_example.py
person = {"name": "မောင်မောင်", "age": 25} try: city = person["city"] # "city" key မရှိဘူး except KeyError as e: print(f"KeyError: {e}") print("Key မရှိပါဘူး") # Better way: use .get() method city = person.get("city", "Unknown") print(f"City: {city}")

6. IndexError:

List/Tuple index က range အပြင်မှာ ရှိတာ

index_error_example.py
numbers = [1, 2, 3] try: value = numbers[5] # index 5 မရှိဘူး except IndexError as e: print(f"IndexError: {e}") print("Index က list ရဲ့ size ထက် ကြီးနေတယ်")

7. AttributeError:

Object မှာ မရှိတဲ့ attribute/method ခေါ်တာ

attribute_error_example.py
try: text = "Hello" result = text.append("World") # str မှာ append() မရှိဘူး except AttributeError as e: print(f"AttributeError: {e}") print("str မှာ append method မရှိဘူး")

8. ImportError / ModuleNotFoundError:

Module import လုပ်လို့ မရတာ

import_error_example.py
try: import non_existent_module except ModuleNotFoundError as e: print(f"ModuleNotFoundError: {e}") print("Module မတွေ့ဘူး၊ pip install လုပ်ဖို့ လိုနိုင်တယ်")

9. NameError:

မရှိတဲ့ variable ကို သုံးတာ

name_error_example.py
try: print(undefined_variable) # ဒီ variable ကို declare မလုပ်ထားဘူး except NameError as e: print(f"NameError: {e}") print("Variable ကို define မလုပ်ထားဘူး")

Multiple Exception Handling

Exception တွေကို ဘယ်လို handle လုပ်မလဲ။

Method 1: Multiple Exceptions in One Block

multiple_in_one.py
try: value = int(input("နံပါတ် ထည့်ပါ: ")) result = 100 / value except (ValueError, ZeroDivisionError) as e: print(f"Error ဖြစ်သွားတယ်: {e}") print("နံပါတ် မှန်မှန် ထည့် (သုည မဟုတ်တာ)")

Method 2: Separate Exception Blocks

separate_blocks.py
try: value = int(input("နံပါတ် ထည့်ပါ: ")) result = 100 / value print(f"Result: {result}") except ValueError: print("နံပါတ်ပဲ ထည့်ပါ!") except ZeroDivisionError: print("သုညနဲ့ မစားနဲ့!")

Method 3: With Generic Catch-All

with_catchall.py
try: value = int(input("နံပါတ် ထည့်ပါ: ")) result = 100 / value print(f"Result: {result}") except ValueError: print("နံပါတ်ပဲ ထည့်ပါ!") except ZeroDivisionError: print("သုညနဲ့ မစားနဲ့!") except Exception as e: # မထင်ထားတဲ့ တခြား error တွေအတွက် print(f"မျှော်လင့်မထားတဲ့ error: {e}")
အကောင်းဆုံး ကတော့:
  • Specific exceptions တွေကို အရင် catch လုပ်ပါ
  • Generic Exception ကို နောက်ဆုံးမှာပဲ သုံး

Raising Exceptions

ကိုယ့်ဘာသာ ကိုယ် exception ပစ်လို့ရတယ်။

Basic raise:

basic_raise.py
def check_age(age): if age < 0: raise ValueError("အသက်က အနုတ် မဖြစ်နိုင်ဘူး") elif age < 18: raise ValueError("၁၈ နှစ်အောက် ဝင်မရဘူး") else: print(f"Welcome! အသက် {age} နှစ်") # Test try: check_age(15) except ValueError as e: print(f"Error: {e}")

Re-raising Exceptions:

reraise_exception.py
def process_file(filename): try: with open(filename, "r") as f: data = f.read() return data except FileNotFoundError: print(f"Logging: {filename} မရှိဘူး") raise # Exception ကို ပြန်ပစ်မယ် try: process_file("missing.txt") except FileNotFoundError: print("Main: File error ကို handle လုပ်နေတယ်")

Output:

Output
Logging: missing.txt မရှိဘူး Main: File error ကို handle လုပ်နေတယ်

Exception Chaining (raise...from):

exception_chaining.py
def load_config(filename): try: with open(filename) as f: data = f.read() return data except FileNotFoundError as e: # Original exception ကို ယူပြီး new exception ပစ်မယ် raise RuntimeError("Config file မ load လို့မရဘူး") from e try: load_config("config.txt") except RuntimeError as e: print(f"Error: {e}") print(f"Original cause: {e.__cause__}")

Custom Exceptions

ကိုယ်ပိုင် exception class တွေလည်း ဆောက်လို့ရသေးတယ်။

Simple Custom Exception:

simple_custom.py
class InvalidAgeError(Exception): """အသက် မမှန်တဲ့အခါ သုံးမယ့် exception""" pass def register_user(name, age): if age < 18: raise InvalidAgeError(f"{name} က ငယ်လွန်းတယ် (အသက်: {age})") print(f"{name} ကို register လုပ်ပြီး") try: register_user("မောင်မောင်", 15) except InvalidAgeError as e: print(f"Registration Error: {e}")

Custom Exception with Attributes:

custom_with_attributes.py
class InsufficientBalanceError(Exception): """ငွေလက်ကျန် မလုံလောက်တဲ့အခါ""" def __init__(self, balance, amount): self.balance = balance self.amount = amount self.shortage = amount - balance message = f"လက်ကျန် မလုံလောက်ဘူး။ လိုအပ်တာ: {amount}, ရှိတာ: {balance}" super().__init__(message) def withdraw(balance, amount): if amount > balance: raise InsufficientBalanceError(balance, amount) return balance - amount try: new_balance = withdraw(1000, 1500) except InsufficientBalanceError as e: print(f"Error: {e}") print(f"လိုအပ်သေးတာ: {e.shortage} ကျပ်")

Exception Hierarchy:

exception_hierarchy.py
class PaymentError(Exception): """Payment error အားလုံးရဲ့ base class""" pass class InsufficientFundsError(PaymentError): """ငွေမလုံလောက်တဲ့ error""" pass class InvalidCardError(PaymentError): """Card မမှန်တဲ့ error""" pass def process_payment(amount, card_valid): if not card_valid: raise InvalidCardError("Card ကို verify လုပ်မရ") if amount > 5000: raise InsufficientFundsError("ငွေမလုံလောက်ဘူး") print("Payment အောင်မြင်ပါတယ်") # Base exception နဲ့ catch လုပ်လို့ရတယ် try: process_payment(6000, True) except PaymentError as e: print(f"Payment Error: {e}")

Assertions (assert statement)

Assert က debugging အတွက် သုံးတာ။ Condition မမှန်ရင် AssertionError ပစ်မယ်။

Basic assert:

basic_assert.py
def divide(a, b): assert b != 0, "Divisor က သုည ဖြစ်မရ" return a / b print(divide(10, 2)) # OK try: print(divide(10, 0)) # AssertionError except AssertionError as e: print(f"Assertion failed: {e}")

Assert for Validation:

assert_validation.py
def calculate_average(scores): assert len(scores) > 0, "Scores list က empty ဖြစ်လို့မရဘူး" assert all(isinstance(s, (int, float)) for s in scores), "အကုန်က numbers ဖြစ်ရမယ်" return sum(scores) / len(scores) # Test print(calculate_average([85, 90, 92])) # OK try: print(calculate_average([])) # AssertionError except AssertionError as e: print(f"Error: {e}")
Important:
  • Assert က development/testing အတွက်ပဲ သုံးနော်
  • Production code မှာ error handling အစစ်တွက် try-except ကိုပဲသုံး
  • Python ကို -O (optimize) flag နဲ့ run ရင် assert တွေ ignore လုပ်တယ်

Logging with Exception Handling

Exception တွေကို log file မှာ မှတ်ထားလို့ရတယ်။

Basic Logging:

basic_logging.py
import logging # Logging setup logging.basicConfig( level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s', filename='app.log' ) try: result = 10 / 0 except ZeroDivisionError as e: logging.error(f"Error occurred: {e}") print("Error logged to app.log")

Logging with Traceback:

logging_traceback.py
import logging logging.basicConfig( level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s', filename='errors.log' ) def divide_numbers(a, b): try: return a / b except ZeroDivisionError: logging.exception("Division by zero attempted") raise try: result = divide_numbers(10, 0) except ZeroDivisionError: print("Error logged with full traceback")

Complete Logging Example:

complete_logging.py
import logging # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('application.log'), logging.StreamHandler() # Console မှာလည်း ပြမယ် ] ) logger = logging.getLogger(__name__) def process_data(data): try: logger.info("Processing data started") # Simulate processing result = 100 / data logger.info(f"Processing completed. Result: {result}") return result except ZeroDivisionError: logger.error("Cannot divide by zero", exc_info=True) return None except Exception as e: logger.exception("Unexpected error occurred") return None # Test process_data(10) # Success process_data(0) # Error

Practical Examples

Example 1: File Reader with Multiple Exceptions

file_reader.py
def read_file_safely(filename): """File ကို ဘေးကင်းကင်း ဖတ်မယ်""" try: with open(filename, "r", encoding="utf-8") as f: content = f.read() print(f"File size: {len(content)} characters") return content except FileNotFoundError: print(f"Error: {filename} ကို ရှာမတွေ့ဘူး") return None except PermissionError: print(f"Error: {filename} ကို ဖတ်ခွင့် မရှိဘူး") return None except UnicodeDecodeError: print(f"Error: {filename} က UTF-8 မဟုတ်ဘူး") # Try with different encoding try: with open(filename, "r", encoding="latin-1") as f: return f.read() except: return None except Exception as e: print(f"Unexpected error: {e}") return None else: print("File ကို ဖတ်ပြီးပြီး") finally: print(f"File operation completed for {filename}") # Test content = read_file_safely("test.txt") if content: print(f"Content: {content[:50]}...")

Example 2: User Input Validator

input_validator.py
def get_integer_input(prompt, min_value=None, max_value=None): """User ကနေ integer input ယူမယ် (validation နဲ့)""" while True: try: value = int(input(prompt)) # Range validation if min_value is not None and value < min_value: print(f"တန်ဖိုးက {min_value} ထက် ကြီးရမယ်") continue if max_value is not None and value > max_value: print(f"တန်ဖိုးက {max_value} ထက် သေးရမယ်") continue return value except ValueError: print("နံပါတ်ပဲ ထည့်ပါ!") except KeyboardInterrupt: print("\nUser က cancel လုပ်လိုက်ပြီ") return None # Test age = get_integer_input("အသက် ထည့်ပါ (18-100): ", 18, 100) if age: print(f"အသက်: {age} နှစ်")

Suggestions

1. Be Specific with Exceptions:

specific_exceptions.py
# Bad try: value = int(input("Number: ")) except: # Catches everything print("Error") # ဂွတ် try: value = int(input("Number: ")) except ValueError: print("Please enter a valid number") except KeyboardInterrupt: print("\nCancelled by user")

2. Don't Swallow Errors:

dont_swallow_errors.py
# Bad try: risky_operation() except: pass # Error ကို skip ပလိုက်တာ! # ဂွတ် import logging try: risky_operation() except Exception as e: logging.error(f"Operation failed: {e}") # Or re-raise raise

3. Use else and finally Appropriately:

else_finally_usage.py
# Good pattern try: f = open("file.txt", "r") except FileNotFoundError: print("File not found") else: # Only runs if no exception content = f.read() print(content) finally: # Always runs - cleanup if 'f' in locals(): f.close()

4. Provide Meaningful Error Messages:

meaningful_messages.py
# Bad try: age = int(input("Age: ")) except ValueError: print("Error") # ဂွတ် try: age = int(input("Age: ")) except ValueError: print("Invalid input. Please enter your age as a number (e.g., 25)")

အနှစ်ချုပ်

Exception Handling အကြောင်း ပြီးပါပြီ။

Key Concepts:

  • try: Error ဖြစ်နိုင်တဲ့ code ရေးတာ
  • except: Error ကို handle လုပ်တာ
  • else: Error မဖြစ်ရင် run မယ့် code
  • finally: ဘာပဲဖြစ်ဖြစ် အမြဲ run မယ့် code (cleanup)
  • raise: Exception ပစ်တာ
  • Custom Exceptions: ကိုယ်ပိုင် exception class တွေ
  • assert: Debugging အတွက် condition check လုပ်တာ

Built-in Exceptions:

  • ValueError, TypeError, ZeroDivisionError
  • FileNotFoundError, KeyError, IndexError
  • AttributeError, ImportError, NameError

Best Practices:

  • Specific exceptions တွေကို catch လုပ်ပါ
  • Error တွေကို silent မဖြစ်အောင်လုပ်သင့်တယ်
  • User ကို clear error message ပြပေး
  • finally ကို cleanup အတွက် သုံးပေါ့။ မသုံးမနေရ ပုံစံမျိုးတော့မဟုတ်။
Exception Handling: Real-world applications တွေမှာ error handling က မဖြစ်မနေ လိုအပ်တယ်။ User experience ကောင်းအောင်၊ program stable ဖြစ်အောင်၊ debugging လွယ်အောင် exception handling ကောင်းကောင်း လုပ်ရမယ်။

Quick Reference

exception_handling_cheatsheet.py
# === Basic Structure === try: # risky code except ExceptionType: # handle error else: # no error finally: # always runs # === Multiple Exceptions === except (ValueError, TypeError): pass # === Get Exception Details === except ValueError as e: print(e) # === Raise Exception === raise ValueError("Error message") # === Re-raise === except ValueError: # do something raise # === Custom Exception === class MyError(Exception): pass # === Assert === assert condition, "message" # === Logging === import logging logging.exception("Error occurred") # === Context Manager === with open("file.txt") as f: data = f.read() # === Suppress === from contextlib import suppress with suppress(FileNotFoundError): open("file.txt")