Notes & software courses · Free to learn
Aph's Blog
On this page

อ่าน Traceback & กลยุทธ์ Debug

👋 อ่านฟรีทั้งหมดบน Aph's Blog — เนื้อหาภาษาไทย ทำตามทีละหน้าใน sidebar ได้เลย หากมีข้อเสนอแนะหรืออยากให้เพิ่มหัวข้อไหน บอกได้เสมอ

อ่าน error message ให้ขาด และไล่หา bug อย่างเป็นระบบ แทนการแก้มั่ว

เมื่อโปรแกรมพัง Python พิมพ์ traceback ออกมา — มันไม่ใช่ "ข้อความน่ากลัว" แต่คือแผนที่บอกว่า error เกิดที่ไหนและเดินทางมายังไง การอ่านมันเป็นช่วยให้แก้ bug ได้ในไม่กี่วินาที และการมีกลยุทธ์ที่เป็นระบบช่วยให้ไม่หลงทาง

อ่าน traceback จากล่างขึ้นบน

traceback อ่าน "บรรทัดล่างสุดก่อน" เพราะนั่นคือชนิด error และข้อความจริง ส่วนข้างบนคือลำดับการเรียกที่นำมาถึงจุดพัง (เก่าสุดอยู่บน ใหม่สุด/จุดพังจริงอยู่ล่าง)

Traceback (most recent call last):
  File "app.py", line 12, in <module>
    main()
  File "app.py", line 8, in main
    result = divide(10, 0)
  File "app.py", line 4, in divide
    return a / b
ZeroDivisionError: division by zero

อ่านล่างขึ้นบน: (1) error คือ ZeroDivisionError: division by zero (2) เกิดที่ app.py บรรทัด 4 ใน divide ที่ return a / b (3) divide ถูกเรียกจาก main บรรทัด 8 (4) main ถูกเรียกจากบรรทัด 12 — เห็นเส้นทางครบ

จุดพังจริงอยู่ล่างสุดเสมอ

บรรทัดสุดท้าย = ชนิด error + ข้อความ; บรรทัด File ... ที่อยู่เหนือมันติดกัน = ตำแหน่งที่ error เกิดจริง อ่านสองอย่างนี้ก่อน แล้วค่อยไล่ขึ้นไปดูว่าถูกเรียกมายังไง

exception chaining ใน traceback

ถ้าใช้ raise ... from ... (จากบท Exception) traceback จะแสดง 2 ส่วนเชื่อมด้วย "The above exception was the direct cause..." — บอกทั้ง error ที่โยนใหม่และต้นตอเดิม

กลยุทธ์ debug 4 ขั้น (ทำตามลำดับ)

อย่าแก้มั่ว ทำตามลำดับนี้จะหา bug ได้เร็วและไม่หลงทาง:

  1. ทำซ้ำให้ได้ก่อน (reproduce) — หา input/ขั้นตอนที่ทำให้พังทุกครั้ง ถ้าทำซ้ำไม่ได้ ยังแก้ไม่ได้
  2. จำกัดวง (narrow down) — แบ่งครึ่งหาว่า bug อยู่ช่วงไหน ด้วย print/breakpoint หรือคอมเมนต์โค้ดออกทีละส่วน
  3. ตั้งสมมติฐาน + พิสูจน์ — เดาว่าอะไรผิด แล้วหาวิธีพิสูจน์/หักล้าง อย่าเดาแล้วแก้เลย
  4. แก้ทีละอย่าง + ยืนยัน — แก้จุดเดียว รันเช็คว่าหาย อย่าแก้หลายอย่างพร้อมกันจนไม่รู้ว่าอะไรได้ผล
ทำซ้ำ bug ให้ได้ก่อนเสมอ

ถ้ายังทำให้ bug เกิดซ้ำไม่ได้ตามต้องการ แสดงว่ายังไม่เข้าใจมันพอจะแก้ การ "แก้" โดยไม่ทำซ้ำได้ มักได้แค่บังเอิญหาย แล้วกลับมาใหม่ — reproduce คือก้าวแรกเสมอ

rubber duck debugging

เทคนิคคลาสสิก: อธิบายโค้ดทีละบรรทัดออกเสียงให้ "เป็ดยาง" (หรืออะไรก็ได้) ฟัง บ่อยครั้งคุณจะเจอจุดผิดเองระหว่างอธิบาย เพราะการเรียบเรียงเป็นคำพูดบังคับให้คิดให้ชัด

สรุปหัวข้อนี้

  • อ่าน traceback จากล่างขึ้นบน: ชนิด error + ตำแหน่งจริงอยู่ล่างสุด
  • ส่วนบนคือเส้นทางการเรียก (call stack) ที่นำมาถึงจุดพัง
  • กลยุทธ์: reproduce → narrow down → ตั้ง+พิสูจน์สมมติฐาน → แก้ทีละอย่าง
  • ทำซ้ำ bug ให้ได้ก่อนแก้เสมอ; ลองอธิบายโค้ดออกเสียง (rubber duck)
แบบฝึกหัด

1) เอา traceback ที่ให้มาบอกว่า error อยู่ไฟล์/บรรทัดไหน เพราะอะไร 2) เขียนโค้ดที่จงใจให้เกิด KeyError แล้วอ่าน traceback หาจุดเกิด 3) ฝึกกลยุทธ์ 4 ขั้นกับ bug จริงในแบบฝึกหัดก่อนหน้า 4) ลอง rubber duck อธิบายฟังก์ชันที่งง ๆ ให้คนอื่น/ตัวเองฟัง