Lỗi là chuyện bình thường. Biết đọc thông báo lỗi và xử lý ngoại lệ giúp chương trình bền vững hơn.
- Đọc hiểu thông báo lỗi (traceback)
- Phân biệt lỗi cú pháp, lỗi chạy, lỗi logic
- Dùng try/except/else/finally
- Chủ động báo lỗi bằng raise
- Ngoại lệ (exception)
- Lỗi xảy ra khi chương trình đang chạy, ví dụ chia cho 0.
- Traceback
- Bản ghi các dòng mã dẫn tới lỗi; đọc từ dưới lên.
- Gỡ lỗi (debug)
- Quá trình tìm và sửa lỗi.
- Lỗi logic
- Chương trình chạy được nhưng cho kết quả sai.
Khái niệm và lý thuyết
Có ba nhóm lỗi: lỗi cú pháp (viết sai quy tắc, chương trình không chạy được), lỗi thời gian chạy (chạy được nhưng gặp tình huống không xử lý nổi, ví dụ chia cho 0) và lỗi logic (chạy trơn tru nhưng kết quả sai). Lỗi logic khó nhất vì máy không báo gì.
Khi lỗi thời gian chạy xảy ra, Python tạo một ngoại lệ (exception). Nếu không ai xử lý, chương trình dừng và in traceback, danh sách các lời gọi hàm dẫn đến lỗi. Cách đọc: dòng cuối cho biết loại lỗi và lý do, các dòng trên cho biết lỗi nằm ở tệp, dòng nào.
Cấu trúc try/except cho phép chương trình "bắt" ngoại lệ và xử lý thay vì sập. Nguyên tắc: chỉ bắt những lỗi bạn dự đoán được và biết cách xử lý (người dùng nhập sai, tệp không tồn tại), còn lỗi lập trình thì nên để lộ ra để sửa. Khối finally luôn chạy, dùng để dọn dẹp như đóng tệp, kết nối.
Các loại lỗi thường gặp
| Lỗi | Nguyên nhân thường gặp |
|---|---|
| SyntaxError | Sai cú pháp: thiếu dấu hai chấm, ngoặc |
| NameError | Dùng biến chưa khai báo hoặc gõ sai tên |
| TypeError | Phép toán sai kiểu, như "5" + 3 |
| ValueError | Giá trị không hợp lệ: int("abc") |
| ZeroDivisionError | Chia cho 0 |
| FileNotFoundError | Tệp không tồn tại |
| IndexError, KeyError | Chỉ số, khóa không có |
Cách đọc traceback: nhìn dòng cuối cùng để biết loại lỗi và lý do, rồi xem số dòng ngay phía trên để biết lỗi ở đâu.
try / except
try:
n = int(input("Nhập số: "))
print(10 / n)
except ValueError:
print("Bạn phải nhập số nguyên")
except ZeroDivisionError:
print("Không chia được cho 0")
else:
print("Không có lỗi")
finally:
print("Luôn chạy, dùng để dọn dẹp")Chủ động báo lỗi
def tinh_tuoi(nam_sinh):
if nam_sinh > 2026:
raise ValueError("Năm sinh không hợp lệ")
return 2026 - nam_sinhVí dụ: chương trình không chết khi người dùng nhập sai
while True:
try:
tuoi = int(input("Nhập tuổi: "))
break
except ValueError:
print("Vui lòng nhập số nguyên, ví dụ 25.")Nếu người dùng gõ "hai mươi", Python sinh lỗi ValueError; khối except bắt lỗi, nhắc nhẹ nhàng rồi yêu cầu nhập lại thay vì dừng chương trình. Khi gặp lỗi, đừng hoảng: đọc dòng cuối cùng của thông báo lỗi, nó cho biết loại lỗi, và dòng ngay trên đó chỉ ra dòng mã gây lỗi.
Cách tìm lỗi logic
In giá trị trung gian bằng print, kiểm tra từng bước với ví dụ nhỏ, hoặc dùng trình gỡ lỗi của VS Code (đặt điểm dừng, bấm F5, xem giá trị biến).
Chương trình hỏi tuổi; người dùng gõ "hai mươi". Thay vì sập, ta hỏi lại đến khi hợp lệ:
while True:
try:
tuoi = int(input("Tuổi: "))
break
except ValueError:
print("Vui lòng nhập số, ví dụ 20")Chỉ bắt đúng loại lỗi bạn dự đoán. Tránh except: trống vì nó giấu cả lỗi bạn không ngờ tới.
Đừng dùng try để che lỗi logic. Hãy sửa nguyên nhân thay vì bỏ qua.
- Viết hàm chia hai số an toàn, trả thông báo khi chia cho 0.
- Mở tệp do người dùng nhập tên; nếu không có thì báo.
- Cố tình tạo 5 loại lỗi trong bảng trên và đọc traceback của từng loại.
- Lỗi phổ biến: SyntaxError, NameError, TypeError, ValueError.
- Đọc traceback từ dòng cuối.
try/exceptxử lý lỗi dự đoán được.raisebáo lỗi khi dữ liệu sai.