Exceptions
Exception คืออะไร
หัวข้อที่มีชื่อว่า “Exception คืออะไร”Exception คือสัญญาณที่บอกว่ามีบางอย่างผิดพลาดระหว่างการรัน
เมื่อ Python raise exception จะ unwind call stack จนกว่าจะเจอ except clause ที่ตรงกัน หรือหยุดโปรแกรม
Exception คือ object — instance ของ class ที่สืบทอดจาก BaseException Exception ที่ใช้งานในโค้ดทั่วไปมักสืบทอดจาก Exception
โครงสร้าง try statement ครบรูปแบบ
หัวข้อที่มีชื่อว่า “โครงสร้าง try statement ครบรูปแบบ”try: result = risky_operation()except SomeError as e: # ทำงานเฉพาะเมื่อ SomeError (หรือ subclass) ถูก raise handle(e)else: # ทำงานเฉพาะเมื่อไม่มี exception เกิดขึ้นใน try use(result)finally: # ทำงานเสมอ — ไม่ว่าจะเกิด exception หรือไม่ cleanup()Block else เป็น feature Python ที่มีประโยชน์: ช่วยแยกแยะ “การดำเนินการสำเร็จ” ออกจาก “เราอยู่ใน cleanup” โค้ดใน else ทำงานเฉพาะเส้นทาง happy path เท่านั้น
การจับ exception ตามประเภทเฉพาะ
หัวข้อที่มีชื่อว่า “การจับ exception ตามประเภทเฉพาะ”จับ exception ที่เฉพาะเจาะจงที่สุดเสมอ การจับ Exception เป็นทางเลือกสุดท้าย ส่วน except: เปล่าจะกลืน KeyboardInterrupt และ SystemExit ไปด้วย
try: n = int(user_input)except ValueError: print("Not a valid integer")except TypeError: print("Expected a string, not None")จับหลายประเภทในบรรทัดเดียวด้วย tuple:
except (ValueError, TypeError) as e: print(f"Input error: {e}")การ raise exception
หัวข้อที่มีชื่อว่า “การ raise exception”ใช้ raise เพื่อส่งสัญญาณ error อย่างชัดเจน:
def divide(a: float, b: float) -> float: if b == 0: raise ValueError("divisor cannot be zero") return a / bRe-raise exception ปัจจุบันภายใน except block ด้วย raise เปล่า:
except ValueError: log_error() raise # re-raise exception เดิมโดยไม่เปลี่ยนแปลงException chaining ด้วย raise ... from
หัวข้อที่มีชื่อว่า “Exception chaining ด้วย raise ... from”เมื่อจับ exception หนึ่งแล้ว raise อีกอัน ให้ใช้ raise NewError(...) from original เพื่อเก็บ exception เดิมไว้เป็นสาเหตุ ทำให้ traceback ครบถ้วน
try: value = int(raw_string)except ValueError as original: raise RuntimeError("Failed to parse config") from originalAttribute __cause__ บน exception ใหม่เก็บ exception เดิมไว้ Python แสดง traceback ทั้งสองอันอัตโนมัติ
หากต้องการตัด chain (ซ่อน traceback เดิม) ใช้ raise ... from None
Demo แบบ runnable เต็มรูปแบบ
หัวข้อที่มีชื่อว่า “Demo แบบ runnable เต็มรูปแบบ”def safe_divide(a: float, b: float) -> float: """Divide a by b, raising ValueError if b is zero.""" if b == 0: raise ValueError("divisor cannot be zero") return a / b
# --- try / except / else / finally ---print("=== basic try/except/else/finally ===")for b in [2.0, 0]: try: result = safe_divide(10.0, b) except ValueError as e: print(f" ValueError: {e}") else: print(f" Result: {result}") finally: print(" finally ran")
# --- catching specific types ---print("\n=== specific exception types ===")for val in ["42", "abc", None]: try: n = int(val) print(f" parsed {val!r} -> {n}") except (TypeError, ValueError) as e: print(f" {type(e).__name__} for {val!r}: {e}")
# --- exception chaining ---print("\n=== exception chaining ===")try: try: raw = "not-a-number" value = int(raw) except ValueError as original: raise RuntimeError("Failed to parse config value") from originalexcept RuntimeError as e: print(f" RuntimeError: {e}") print(f" __cause__: {e.__cause__}")Loading Python runtime (first run only)…