Trong Python, ngoại lệ (exceptions) là những lỗi có thể xảy ra khi chương trình chạy. Nếu không xử lý, chương trình sẽ bị dừng đột ngột.
1️⃣ Syntax Errors (Lỗi cú pháp)
Lỗi xảy ra do sai cú pháp khi viết code.
print("hello, world) # ❌ Lỗi: thiếu dấu "✅ Cách khắc phục: Kiểm tra cú pháp cẩn thận!
2️⃣ Runtime Errors (Lỗi khi chạy chương trình)
Lỗi xảy ra trong quá trình thực thi chương trình, ví dụ như nhập sai kiểu dữ liệu.
🔹 Ví dụ lỗi **ValueError**
python
CopyEdit
x = int(input("What's x? "))
# ❌ Lỗi nếu nhập "cat"
print(f"x is {x}")
-> ValueError: invalid literal for int() with base 10: 'cat'✅ Giải pháp: Dùng try-except để xử lý lỗi.
3️⃣ **try-except** để xử lý ngoại lệ
Dùng try để chạy đoạn code có thể gây lỗi, và except để xử lý lỗi.
try:
x = int(input("What's x? "))
print(f"x is {x}")
except ValueError:
print("x is not an integer")📌 Cách hoạt động:
- Nếu nhập số, chương trình chạy bình thường.
- Nếu nhập sai (
"cat"), chương trình in"x is not an integer".
4️⃣ Viết **try** ngắn gọn hơn
📌 Không nên viết **try** bao toàn bộ đoạn code nếu không cần thiết:
python
CopyEdit
try:
x = int(input("What's x? "))
except ValueError:
print("x is not an integer")
print(f"x is {x}") # ❌ Lỗi nếu `x` chưa được gán giá trị!Lỗi xảy ra: NameError: name 'x' is not defined
✅ Dùng **else** để đảm bảo **x** chỉ được dùng khi không có lỗi
python
CopyEdit
try:
x = int(input("What's x? "))
except ValueError:
print("x is not an integer")
else:
print(f"x is {x}") # Chỉ chạy nếu không có lỗi5️⃣ Dùng **while True** để liên tục yêu cầu nhập đúng
while True:
try:
x = int(input("What's x? "))
except ValueError:
print("x is not an integer")
else:
break # Nếu nhập đúng, thoát vòng lặp
print(f"x is {x}")📌 Cách hoạt động:
- Nếu nhập sai, tiếp tục yêu cầu nhập lại.
- Nếu nhập đúng,
breakđể thoát khỏi vòng lặp.
6️⃣ Viết **get_int()** để tái sử dụng
✅ Dùng hàm để nhập số nguyên
def main():
x = get_int()
print(f"x is {x}")
def get_int():
while True:
try:
x = int(input("What's x? "))
except ValueError:
print("x is not an integer")
else:
return x # Trả về giá trị hợp lệ
main()✅ Viết gọn hơn nữa
python
CopyEdit
def get_int():
while True:
try:
return int(input("What's x? "))
except ValueError:
print("x is not an integer")✅ Hoặc không in thông báo lỗi (**pass**)
python
CopyEdit
def get_int():
while True:
try:
return int(input("What's x? "))
except ValueError:
pass # Bỏ qua lỗi, yêu cầu nhập lại✅ Truyền **prompt** vào **get_int()**
python
CopyEdit
def main():
x = get_int("Enter a number: ")
print(f"x is {x}")
def get_int(prompt):
while True:
try:
return int(input(prompt))
except ValueError:
pass
main()📌 Ưu điểm: Dễ tái sử dụng với các câu hỏi khác nhau.
7️⃣ Các loại ngoại lệ phổ biến
| Ngoại lệ | Khi nào xảy ra? | Ví dụ |
ValueError | Chuyển đổi kiểu dữ liệu sai | int("hello") |
ZeroDivisionError | Chia cho 0 | 5 / 0 |
IndexError | Truy cập phần tử ngoài phạm vi list | my_list[10] |
KeyError | Truy cập key không tồn tại trong dict | my_dict["key"] |
TypeError | Sử dụng sai kiểu dữ liệu | "5" + 3 |
✅ Dùng **except** cho nhiều lỗi |
python
CopyEdit
try:
num = int(input("Enter a number: "))
result = 10 / num
except ValueError:
print("Invalid input! Please enter a number.")
except ZeroDivisionError:
print("You can't divide by zero!")Debugging
Debugging (gỡ lỗi) trong Python là quá trình tìm và sửa lỗi trong mã nguồn của chương trình. Khi chạy một chương trình Python, có thể gặp phải các lỗi như:
- Lỗi cú pháp (Syntax Errors): Viết sai cú pháp của Python.
- Lỗi logic (Logical Errors): Chương trình chạy nhưng không cho ra kết quả như mong muốn.
- Lỗi runtime (Runtime Errors): Lỗi xảy ra trong quá trình chạy chương trình, chẳng hạn như chia cho 0 hoặc truy cập một biến chưa được khai báo.
Cách Debug trong Python
1. Sử dụng **print()** để kiểm tra giá trị
Cách đơn giản nhất để debug là thêm các dòng print() vào mã để kiểm tra giá trị biến tại từng bước.
Ví dụ:
def tinh_tong(a, b):
print("Giá trị của a:", a)
print("Giá trị của b:", b)
return a + b
print(tinh_tong(5, 10))2. Debug với IDE (Visual Studio Code, PyCharm)
Các IDE như PyCharm và VS Code có sẵn debugger hỗ trợ đặt breakpoint và chạy từng dòng. Breakpoint: Là điểm dừng trong đoạn code, để có thể kiểm tra biến, giá trị và luồng xử lý.
- Trong VS Code:
- Mở file Python.
- Đặt breakpoint bằng cách click vào lề trái của dòng code.
- Chạy bằng chế độ Debug (F5).

Continue (**F5**)
- Chức năng: Tiếp tục chạy chương trình cho đến khi gặp breakpoint tiếp theo hoặc kết thúc.
- Khi nào dùng? Khi bạn muốn bỏ qua các dòng code hiện tại và chạy đến breakpoint kế tiếp.
Step Over (**F10**)
- Chức năng: Chạy từng dòng code một nhưng không đi vào bên trong các hàm (nếu có hàm trong dòng code, nó sẽ chạy toàn bộ hàm đó mà không dừng bên trong).
- Khi nào dùng? Khi bạn chỉ quan tâm đến dòng code hiện tại và không cần xem chi tiết bên trong các hàm. Ví dụ:
def tinh_tong(a, b):
return a + b
x = 5
y = 10
tong = tinh_tong(x, y) # Nếu bấm "Step Over", nó sẽ chạy hàm mà không vào bên trong hàm `tinh_tong`
print(tong)Step Into (**F11**)
- Chức năng: Chạy từng dòng code và đi vào bên trong các hàm nếu có.
- Khi nào dùng? Khi bạn muốn xem chi tiết code bên trong một hàm. Ví dụ:
def tinh_tong(a, b):
return a + b
x = 5
y = 10
tong = tinh_tong(x, y) # Nếu bấm "Step Into", VS Code sẽ đi vào hàm `tinh_tong`
print(tong)Step Out (**Shift + F11**)
- Chức năng: Nếu bạn đang ở bên trong một hàm, nút này sẽ chạy hết phần còn lại của hàm và quay lại nơi nó được gọi.
- Khi nào dùng? Khi bạn đã xem đủ chi tiết bên trong một hàm và muốn quay lại luồng chính. Ví dụ:
def tinh_tong(a, b):
result = a + b # Nếu bạn đang dừng ở đây và bấm "Step Out", nó sẽ chạy xong hàm và quay lại nơi `tinh_tong` được gọi
return result
x = 5
y = 10
tong = tinh_tong(x, y)
print(tong)Restart (**Ctrl + Shift + F5**)
- Chức năng: Dừng chương trình và chạy lại từ đầu.
- Khi nào dùng? Khi bạn muốn reset chương trình và debug lại từ đầu.
Stop (**Shift + F5**)
- Chức năng: Dừng hoàn toàn chương trình debug.
- Khi nào dùng? Khi bạn không muốn tiếp tục debug nữa.
Handling Exceptions
Exception Handling là cách xử lý lỗi trong Python để tránh chương trình bị dừng đột ngột. Khi gặp lỗi, Python sẽ ném ra một Exception, nếu không được xử lý, chương trình sẽ bị dừng.
1. Cấu trúc Try-Except cơ bản
Dùng try-except để bắt lỗi và xử lý mà không làm gián đoạn chương trình.
Ví dụ: Bắt lỗi chia cho 0
python
CopyEdit
try:
x = 10 / 0 # Lỗi ZeroDivisionError
except ZeroDivisionError:
print("Lỗi: Không thể chia cho 0!")Kết quả:
less
CopyEdit
Lỗi: Không thể chia cho 0!→ Chương trình không bị dừng, thay vào đó, lỗi được xử lý.
2. Bắt nhiều loại lỗi
Có thể bắt nhiều loại lỗi khác nhau bằng cách thêm nhiều khối except.
Ví dụ:
python
CopyEdit
try:
x = int("abc") # Lỗi ValueError
y = 10 / 0 # Lỗi ZeroDivisionError
except ValueError:
print("Lỗi: Không thể chuyển đổi chuỗi sang số!")
except ZeroDivisionError:
print("Lỗi: Không thể chia cho 0!")Kết quả:
less
CopyEdit
Lỗi: Không thể chuyển đổi chuỗi sang số!→ Khi gặp lỗi đầu tiên (ValueError), chương trình sẽ xử lý và không kiểm tra ZeroDivisionError.
3. Bắt tất cả lỗi với **Exception**
Dùng Exception để bắt tất cả các loại lỗi.
Ví dụ:
python
CopyEdit
try:
x = 10 / 0
except Exception as e:
print(f"Lỗi xảy ra: {e}")Kết quả:
csharp
CopyEdit
Lỗi xảy ra: division by zero→ Lệnh except Exception as e giúp in chi tiết lỗi.
4. Sử dụng **else** để chạy nếu không có lỗi
Khối else sẽ chạy nếu không có lỗi xảy ra trong try.
Ví dụ:
python
CopyEdit
try:
x = 10 / 2
except ZeroDivisionError:
print("Lỗi: Không thể chia cho 0!")
else:
print(f"Kết quả: {x}")Kết quả:
mathematica
CopyEdit
Kết quả: 5.0→ Vì không có lỗi, khối else được thực thi.
5. Sử dụng **finally** để luôn chạy
Khối finally sẽ luôn chạy dù có lỗi hay không.
Ví dụ:
python
CopyEdit
try:
x = 10 / 0
except ZeroDivisionError:
print("Lỗi: Không thể chia cho 0!")
finally:
print("Luôn chạy dòng này!")Kết quả:
less
CopyEdit
Lỗi: Không thể chia cho 0!
Luôn chạy dòng này!→ finally hữu ích khi cần dọn dẹp tài nguyên, như đóng file hoặc kết nối database.
6. Tự tạo Exception bằng **raise**
Bạn có thể tự tạo lỗi bằng raise.
Ví dụ:
python
CopyEdit
def kiem_tra_tuoi(tuoi):
if tuoi < 18:
raise ValueError("Tuổi phải từ 18 trở lên!")
return "Đủ tuổi!"
try:
print(kiem_tra_tuoi(16))
except ValueError as e:
print(f"Lỗi: {e}")Kết quả:
less
CopyEdit
Lỗi: Tuổi phải từ 18 trở lên!7. Exception Logging (Ghi log lỗi)
Thay vì chỉ in lỗi, bạn có thể ghi lỗi vào file.
Ví dụ với **logging**:
python
CopyEdit
import logging
logging.basicConfig(filename="error.log", level=logging.ERROR)
try:
x = 10 / 0
except Exception as e:
logging.error(f"Lỗi: {e}")
print("Đã ghi lỗi vào file log.")Kết quả:
bash
CopyEdit
Đã ghi lỗi vào file log.→ Lỗi được lưu vào error.log.