บทที่ 10

การจัดการข้อผิดพลาด

Error Handling - try, except

เรียนรู้การจัดการ Error ให้โปรแกรมไม่หยุดทำงาน

🎯 จุดประสงค์การเรียนรู้

• เข้าใจสาเหตุและประเภทของ Error

• ใช้ try-except จัดการ Error ได้

• สร้างโปรแกรมที่ทนต่อข้อผิดพลาด

• แก้ไขปัญหาและ Debug โค้ดได้

Error คืออะไร?

💥 เมื่อโปรแกรมไม่สามารถทำงานต่อได้

Error เกิดขึ้นเมื่อ Python ไม่เข้าใจหรือไม่สามารถทำตามคำสั่งได้

❌ ตัวอย่าง Error

# หารด้วย 0
print(10 / 0)  # ZeroDivisionError

# แปลงข้อความเป็นตัวเลขไม่ได้
age = int("สิบหก")  # ValueError

# เข้าถึงไฟล์ที่ไม่มี
file = open("ไม่มีไฟล์นี้.txt")  # FileNotFoundError

✅ โปรแกรมหยุดทำงาน

เมื่อเกิด Error:

• โปรแกรมหยุดทำงานทันที

• แสดงข้อความ Error

• ไม่ทำคำสั่งต่อไป

• ผู้ใช้งานสับสน

💡 เป้าหมาย: สร้างโปรแกรมที่ "ทนทาน" ไม่หยุดทำงานง่ายๆ

ประเภท Error ที่พบบ่อย

ValueError

ค่าผิดประเภท

แปลงข้อมูลไม่ได้

int("abc")  # Error!
float("xyz")  # Error!
ZeroDivisionError

หารด้วยศูนย์

ไม่สามารถหารด้วย 0

print(5 / 0)  # Error!
print(10 % 0)  # Error!
IndexError

ตำแหน่งไม่มี

เข้าถึงตำแหน่งที่ไม่มี

lst = [1, 2, 3]
print(lst[10])  # Error!
KeyError

Key ไม่มี

หา Key ใน Dict ไม่เจอ

d = {"a": 1}
print(d["b"])  # Error!

🏃‍♂️ แบบฝึกหัด

ลองรันโค้ดด้านบนดู Error ที่เกิดขึ้น

try-except พื้นฐาน

🛡️ ป้องกันโปรแกรมไม่ให้หยุดทำงาน

ใช้ try-except "ลอง" ทำงาน ถ้า Error ก็ "จัดการ" แทน

🔴 ไม่มี Error Handling

# โปรแกรมจะหยุดถ้า Error
age_text = input("อายุ: ")
age = int(age_text)  # Error ถ้าใส่ตัวอักษร
print(f"คุณอายุ {age} ปี")

🟢 มี Error Handling

# โปรแกรมไม่หยุด แม้มี Error
age_text = input("อายุ: ")
try:
    age = int(age_text)
    print(f"คุณอายุ {age} ปี")
except:
    print("กรุณาใส่ตัวเลข")
# โครงสร้าง try-except
try:
    # โค้ดที่อาจมี Error
    result = 10 / 0
except:
    # ทำเมื่อมี Error
    print("เกิดข้อผิดพลาด!")

จับ Error เฉพาะประเภท

🎯 จัดการแต่ละประเภท Error แยกกัน

ใช้ except ระบุประเภท Error เฉพาะ

# จัดการ Error แต่ละประเภท
def safe_divide():
    try:
        a = float(input("ตัวตั้ง: "))
        b = float(input("ตัวหาร: "))
        result = a / b
        print(f"ผลลัพธ์: {result}")
    
    except ValueError:
        print("❌ กรุณาใส่ตัวเลขเท่านั้น")
    
    except ZeroDivisionError:
        print("❌ ไม่สามารถหารด้วย 0 ได้")

safe_divide()
# จัดการหลาย Error พร้อมกัน
def get_student_score(students, index):
    try:
        score = students[index]["score"]
        return score
    
    except IndexError:
        print("❌ ไม่มีนักเรียนคนนี้")
        return 0
    
    except KeyError:
        print("❌ ไม่มีข้อมูลคะแนน")
        return 0
💡 เทคนิค: จัดการ Error เฉพาะจะทำให้ข้อความ Error ชัดเจนกว่า

else และ finally

else

ทำเมื่อไม่มี Error

รันเมื่อ try สำเร็จ

try:
    result = 10 / 2
except:
    print("Error!")
else:
    print("สำเร็จ!")
finally

ทำเสมอ

รันไม่ว่าจะมี Error หรือไม่

try:
    file = open("data.txt")
except:
    print("ไม่พบไฟล์")
finally:
    print("เสร็จแล้ว")
# ตัวอย่างครบครัน
def process_score():
    try:
        score = int(input("คะแนน (0-100): "))
        if score < 0 or score > 100:
            raise ValueError("คะแนนต้องอยู่ระหว่าง 0-100")
    
    except ValueError as e:
        print(f"❌ ข้อผิดพลาด: {e}")
        return 0
    
    else:
        print(f"✅ คะแนนที่ได้: {score}")
        return score
    
    finally:
        print("📝 เสร็จสิ้นการประมวลผล")

ตัวอย่างการใช้งานจริง

🔄 ลูปที่ไม่หยุดจนกว่าจะได้ข้อมูลถูกต้อง

ใช้ Error Handling ร่วมกับ while loop

# ฟังก์ชันรับตัวเลขที่ปลอดภัย
def get_safe_number(prompt, min_val=None, max_val=None):
    """รับตัวเลขจากผู้ใช้อย่างปลอดภัย"""
    while True:
        try:
            number = float(input(prompt))
            
            # ตรวจสอบช่วงค่า
            if min_val is not None and number < min_val:
                print(f"❌ ต้องมากกว่าหรือเท่ากับ {min_val}")
                continue
            
            if max_val is not None and number > max_val:
                print(f"❌ ต้องน้อยกว่าหรือเท่ากับ {max_val}")
                continue
            
            return number
        
        except ValueError:
            print("❌ กรุณาใส่ตัวเลขเท่านั้น")

# ตัวอย่างการใช้
age = get_safe_number("อายุ (0-120): ", 0, 120)
score = get_safe_number("คะแนน (0-100): ", 0, 100)

print(f"✅ อายุ: {age:.0f} ปี")
print(f"✅ คะแนน: {score:.1f}")

จัดการไฟล์อย่างปลอดภัย

📁 อ่านและเขียนไฟล์โดยไม่ให้โปรแกรมหยุด

ใช้ try-except กับการจัดการไฟล์

# อ่านไฟล์อย่างปลอดภัย
def safe_read_file(filename):
    try:
        with open(filename, 'r', encoding='utf-8') as file:
            content = file.read()
            return content
    
    except FileNotFoundError:
        print(f"❌ ไม่พบไฟล์: {filename}")
        return ""
    
    except PermissionError:
        print(f"❌ ไม่มีสิทธิ์เข้าถึงไฟล์: {filename}")
        return ""
    
    except Exception as e:
        print(f"❌ เกิดข้อผิดพลาด: {e}")
        return ""

# บันทึกไฟล์อย่างปลอดภัย
def safe_write_file(filename, content):
    try:
        with open(filename, 'w', encoding='utf-8') as file:
            file.write(content)
        print(f"✅ บันทึกไฟล์สำเร็จ: {filename}")
        return True
    
    except Exception as e:
        print(f"❌ ไม่สามารถบันทึกไฟล์ได้: {e}")
        return False

# ตัวอย่างการใช้งาน
content = safe_read_file("notes.txt")
if content:
    print(f"ไฟล์มีเนื้อหา: {len(content)} ตัวอักษร")
else:
    print("ไม่สามารถอ่านไฟล์ได้")
💡 เทคนิค: ใช้ Exception เป็นชื่อทั่วไปสำหรับ Error ที่ไม่คาดคิด

โปรเจกต์รวม: เครื่องคิดเลขปลอดภัย

🧮 สร้างเครื่องคิดเลขที่ไม่หยุดทำงาน

ใช้ Error Handling ทุกแบบที่เรียนมา

# เครื่องคิดเลขที่ทนทานต่อ Error
def safe_calculator():
    print("🧮 เครื่องคิดเลขปลอดภัย")
    print("พิมพ์ 'quit' เพื่อออก\n")
    
    while True:
        try:
            # รับข้อมูลจากผู้ใช้
            expression = input("คำนวณ (เช่น 5+3): ").strip()
            
            # ตรวจสอบการออก
            if expression.lower() == 'quit':
                print("👋 ขอบคุณที่ใช้งาน!")
                break
            
            # ตรวจสอบว่าไม่ใช่ข้อความว่าง
            if not expression:
                print("❌ กรุณาใส่การคำนวณ")
                continue
            
            # คำนวณโดยใช้ eval (ระวัง: ใช้ได้เฉพาะตัวเลขง่ายๆ)
            result = eval(expression)
            print(f"✅ ผลลัพธ์: {result}\n")
        
        except ZeroDivisionError:
            print("❌ ไม่สามารถหารด้วย 0 ได้\n")
        
        except SyntaxError:
            print("❌ รูปแบบการคำนวณไม่ถูกต้อง\n")
        
        except NameError:
            print("❌ ใช้ได้เฉพาะตัวเลขและเครื่องหมาย +, -, *, /\n")
        
        except Exception as e:
            print(f"❌ เกิดข้อผิดพลาด: {e}\n")

# ฟังก์ชันเครื่องคิดเลขแบบปลอดภัยกว่า
def simple_calculator():
    operations = {'+': lambda x, y: x + y, '-': lambda x, y: x - y,
                   '*': lambda x, y: x * y, '/': lambda x, y: x / y}
    
    print("🔢 เครื่องคิดเลขง่าย (พิมพ์ 'q' เพื่อออก)")
    
    while True:
        try:
            num1 = input("ตัวเลขแรก: ")
            if num1.lower() == 'q': break
            
            op = input("เครื่องหมาย (+, -, *, /): ")
            num2 = input("ตัวเลขที่สอง: ")
            
            n1, n2 = float(num1), float(num2)
            
            if op in operations:
                result = operations[op](n1, n2)
                print(f"✅ {n1} {op} {n2} = {result}\n")
            else:
                print("❌ เครื่องหมายไม่ถูกต้อง\n")
        
        except ValueError:
            print("❌ กรุณาใส่ตัวเลข\n")
        except ZeroDivisionError:
            print("❌ ไม่สามารถหารด้วย 0\n")

# เรียกใช้โปรแกรม
# simple_calculator()

🎉 ความรู้ที่ได้จากบทนี้

• รู้จักประเภท Error ที่พบบ่อยและสาเหตุ

• ใช้ try-except จัดการ Error เฉพาะประเภท

• เข้าใจการทำงานของ else และ finally

• สร้างโปรแกรมที่ทนทานต่อข้อผิดพลาด

• จัดการไฟล์และ Input อย่างปลอดภัย

• เขียนโปรแกรมที่ User-friendly