Kodokon kodokon.com

ข้อผิดพลาดและข้อยกเว้น: try, except, raise

ดักจับความล้มเหลวที่คาดการณ์ได้ด้วย try/except/else/finally และโยนข้อยกเว้นของคุณเองเพื่อแจ้งว่าข้อมูลไม่ถูกต้อง

9 นาที · 3 คำถาม

เปิดบทเรียนนี้ใน Kodokon

โปรแกรมจริงย่อมล้มเหลวได้ ไฟล์หาย ข้อมูลนำเข้าไม่ถูกต้อง เครือข่ายหลุด Python แจ้งสถานการณ์เหล่านี้ด้วย ข้อยกเว้น (exceptions) ซึ่งจะขัดจังหวะการทำงานและส่งต่อขึ้นไปตามกองซ้อนการเรียก จนกว่าจะมี try/except มาดักจับไว้ สัญชาตญาณของมืออาชีพคือ ดักจับ ข้อยกเว้นที่เจาะจงที่สุดเท่าที่ทำได้ ให้ใกล้ที่สุดกับจุดที่คุณรู้ว่าต้องทำอย่างไร

PYTHON
def parse_age(text):
    try:
        return int(text)
    except ValueError:
        return None

print(parse_age("34"))      # 34
print(parse_age("thirty"))  # None
เราดักจับ ValueError อย่างเจาะจง ไม่ใช่ดักจับข้อผิดพลาดทุกชนิด

บล็อกฉบับเต็มมีสี่ส่วน try บรรจุโค้ดที่เสี่ยง except จัดการกับความล้มเหลว else ทำงาน เฉพาะเมื่อไม่มีข้อยกเว้น เกิดขึ้น และ finally ทำงาน ในทุกกรณี - เหมาะสำหรับคืนทรัพยากรหรือบันทึกล็อก ประโยชน์ของ else คือ ทำให้ try เล็กที่สุด คุณจึงเห็นได้ในพริบตาว่าบรรทัดไหนที่อาจล้มเหลว

PYTHON
values = ["10", "abc", "25"]
total = 0

for value in values:
    try:
        number = int(value)
    except ValueError:
        print(f"Skip : {value}")
    else:
        total += number
    finally:
        print(f"Process : {value}")

print(total)  # 35
else ทำงานเฉพาะเมื่อไม่มีข้อผิดพลาด ส่วน finally ทำงานเสมอ

ฟังก์ชันของคุณเองก็ โยน ข้อยกเว้นได้ด้วย raise ทันทีที่ข้อมูลที่รับเข้ามาไม่ถูกต้อง เพราะการล้มเหลวทันทีพร้อมข้อความที่ชัดเจน ย่อมดีกว่าการให้ผลลัพธ์ที่ผิด จงนิยามคลาสเฉพาะที่สืบทอดจาก Exception ผู้เรียกจะได้ดักจับมันอย่างเจาะจง โดยไม่เผลอไปดักข้อผิดพลาดอื่นด้วย

PYTHON
class EmptyCartError(Exception):
    pass

def checkout(items):
    if not items:
        raise EmptyCartError("Empty cart.")
    return round(sum(items), 2)

try:
    print(checkout([]))
except EmptyCartError as error:
    print(f"Error : {error}")
ข้อยกเว้นเฉพาะทางธุรกิจทำให้ความล้มเหลวชัดเจนและตรงจุด

ทดสอบความรู้

ตรวจสอบว่าคุณจำประเด็นสำคัญของบทเรียนนี้ได้ครบถ้วน

  1. บล็อก else ของ try/except ทำงานเมื่อใด?
    • เฉพาะเมื่อไม่มีข้อยกเว้นเกิดขึ้นใน try
    • เฉพาะเมื่อมีข้อยกเว้นถูกดักจับ
    • ในทุกกรณี หลังจาก try
  2. บล็อก finally ทำงานในกรณีใดบ้าง?
    • เฉพาะเมื่อมีข้อยกเว้นเกิดขึ้น
    • เฉพาะเมื่อไม่มีข้อยกเว้นเกิดขึ้น
    • ในทุกกรณี ไม่ว่าจะมีข้อยกเว้นหรือไม่
  3. ทำไมจึงควรเลี่ยง except: เปล่า ๆ ที่ดักจับทุกอย่าง?
    • มันซ่อนบั๊กจริง ๆ ไว้ และทำให้การไล่หาบั๊กยากมาก
    • มันช้ากว่า except ที่เจาะจง
    • มันใช้ได้กับข้อยกเว้นของไลบรารีมาตรฐานเท่านั้น