On this page
สร้าง Exception เอง & raise
นิยามข้อผิดพลาดของโดเมนงานเอง เพื่อให้ผู้เรียกจับและจัดการได้ตรงจุด
บางครั้ง error ที่มีอยู่ใน Python ไม่สื่อความหมายของปัญหาในงานเรา เช่น "เงินไม่พอ" หรือ "อายุไม่ถึง" การสร้าง exception ของตัวเองทำให้โค้ดอ่านง่ายและให้ผู้เรียกจับเฉพาะ error ของเราได้
raise — โยน exception ออกมาเอง
เมื่อเจอสถานการณ์ที่ไม่ควรดำเนินต่อ ให้ raise เพื่อหยุดและส่งสัญญาณว่าเกิดอะไร แทนที่จะคืนค่าแปลก ๆ เช่น -1 หรือ None ที่ผู้เรียกอาจลืมเช็ค
def set_age(age):
if age < 0:
raise ValueError(f"อายุติดลบไม่ได้: {age}")
return age
set_age(-5) # ValueError: อายุติดลบไม่ได้: -5สร้าง custom exception class
สร้างคลาสที่สืบทอดจาก Exception ก็ได้ exception ใหม่แล้ว ตั้งชื่อให้สื่อความหมาย ลงท้ายด้วย Error ตามธรรมเนียม
class InsufficientFundsError(Exception):
"""ยอดเงินไม่พอสำหรับการถอน"""
pass
class Account:
def __init__(self, balance):
self.balance = balance
def withdraw(self, amount):
if amount > self.balance:
raise InsufficientFundsError(
f"ถอน {amount} ไม่ได้ มีแค่ {self.balance}"
)
self.balance -= amount
return self.balance
acc = Account(100)
try:
acc.withdraw(500)
except InsufficientFundsError as e:
print(f"ถอนไม่สำเร็จ: {e}") # จับเฉพาะ error ของเราcustom exception ทำให้ผู้เรียกจับเฉพาะปัญหาของโดเมนได้ (เช่น except InsufficientFundsError) แยกออกจาก ValueError ทั่วไป โค้ดสื่อความหมายขึ้น และเพิ่มข้อมูลในคลาสได้ภายหลัง
เก็บข้อมูลเพิ่มใน exception
class ValidationError(Exception):
def __init__(self, field, message):
self.field = field # เก็บว่า field ไหนผิด
super().__init__(f"{field}: {message}")
try:
raise ValidationError("email", "รูปแบบไม่ถูกต้อง")
except ValidationError as e:
print(e.field) # email (เข้าถึงข้อมูลเพิ่มได้)
print(e) # email: รูปแบบไม่ถูกต้องException Chaining (raise ... from ...)
เมื่อจับ error หนึ่งแล้วโยน error อีกตัว ใช้ from เพื่อบอกที่มา ทำให้ traceback แสดงต้นตอเดิมด้วย — ดีต่อการ debug (เจอใน traceback บทถัดไป)
def load_config(path):
try:
with open(path) as f:
return f.read()
except FileNotFoundError as e:
raise RuntimeError("โหลด config ไม่ได้") from e
# traceback จะแสดงทั้ง RuntimeError และต้นตอ FileNotFoundErrorสรุปหัวข้อนี้
- raise หยุดและส่งสัญญาณข้อผิดพลาด ดีกว่าคืนค่าแปลก ๆ ที่อาจลืมเช็ค
- custom exception = class สืบจาก Exception ตั้งชื่อลงท้าย Error
- เก็บข้อมูลเพิ่มใน exception ได้ผ่าน __init__
- raise ... from ... ระบุที่มา ช่วย debug
1) สร้าง custom exception ชื่อ AgeTooYoungError แล้วใช้ในฟังก์ชันสมัครสมาชิก (ต้องอายุ >= 18) 2) เพิ่มข้อมูล field ใน ValidationError 3) เขียนฟังก์ชันโหลดไฟล์ที่ใช้ raise ... from ... 4) อธิบายข้อดีของ custom exception เทียบกับ ValueError ทั่วไป