Bỏ qua để đến nội dung

Exception Handling (Try/Except)

Exception (ngoại lệ) là lỗi xảy ra khi chương trình đang chạy. Nếu không xử lý, chương trình sẽ dừng đột ngột.

Exception Handling (xử lý ngoại lệ) giúp chương trình:

  • Không bị crash khi gặp lỗi
  • Xử lý lỗi một cách có kiểm soát
  • Hiển thị thông báo lỗi thân thiện với người dùng
try:
# Code có thể gây lỗi
risky_operation()
except:
# Code xử lý khi có lỗi
print("Có lỗi xảy ra!")
# Không xử lý lỗi - Chương trình crash!
# result = 10 / 0 # ZeroDivisionError
# Có xử lý lỗi - Chương trình tiếp tục chạy
try:
result = 10 / 0
print(result)
except:
print("Không thể chia cho 0!")
print("Chương trình vẫn chạy tiếp")

2.3 - Ví dụ: Chuyển đổi kiểu dữ liệu

Phần tiêu đề “2.3 - Ví dụ: Chuyển đổi kiểu dữ liệu”
user_input = "abc"
try:
number = int(user_input)
print(f"Số bạn nhập: {number}")
except:
print("Vui lòng nhập một số hợp lệ!")

Bắt exception cụ thể giúp:

  • Xử lý từng loại lỗi khác nhau
  • Code dễ đọc và maintain hơn
  • Debug dễ dàng hơn
try:
risky_operation()
except ValueError:
print("Lỗi giá trị không hợp lệ")
except ZeroDivisionError:
print("Lỗi chia cho 0")
try:
age = int(input("Nhập tuổi: "))
result = 100 / age
print(f"Kết quả: {result}")
except ValueError:
print("Tuổi phải là một số!")
except ZeroDivisionError:
print("Tuổi không thể là 0!")
Exception Khi nào xảy ra Ví dụ
ValueError Giá trị không đúng kiểu int("abc")
ZeroDivisionError Chia cho 0 10 / 0
TypeError Sai kiểu dữ liệu "hello" + 5
IndexError Index vượt quá phạm vi [1,2,3][10]
KeyError Key không tồn tại dict["key"]
FileNotFoundError File không tồn tại open("xyz.txt")
AttributeError Thuộc tính không tồn tại "hello".xyz()
NameError Biến chưa được định nghĩa print(x)
# ValueError
try:
number = int("abc")
except ValueError as e:
print(f"ValueError: {e}")
# IndexError
try:
my_list = [1, 2, 3]
print(my_list[10])
except IndexError as e:
print(f"IndexError: {e}")
# KeyError
try:
my_dict = {"name": "Alice"}
print(my_dict["age"])
except KeyError as e:
print(f"KeyError: {e}")
try:
result = 10 / 0
except ZeroDivisionError as error:
print(f"Lỗi: {error}")
print(f"Loại lỗi: {type(error).__name__}")

Kết quả:

Lỗi: division by zero
Loại lỗi: ZeroDivisionError
try:
number = int(input("Nhập số: "))
result = 100 / number
print(result)
except ValueError:
print("Vui lòng nhập số!")
except ZeroDivisionError:
print("Không thể chia cho 0!")
try:
# Code
pass
except (ValueError, TypeError, ZeroDivisionError) as e:
print(f"Lỗi: {e}")

6.3 - Bắt tất cả Exception (không khuyến khích)

Phần tiêu đề “6.3 - Bắt tất cả Exception (không khuyến khích)”
try:
# Code
pass
except Exception as e:
print(f"Có lỗi: {e}")
try:
number = int(input("Nhập số: "))
except ValueError:
print("Số không hợp lệ!")
else:
print(f"Bạn đã nhập: {number}")
print("Không có lỗi xảy ra!")
try:
file = open("data.txt", "r")
content = file.read()
except FileNotFoundError:
print("File không tồn tại!")
else:
print("Đọc file thành công!")
finally:
print("Khối này luôn chạy")
# Đóng file nếu đã mở
try:
file.close()
except:
pass
try:
# Code có thể gây lỗi
result = 10 / 2
except ZeroDivisionError:
# Xử lý lỗi chia 0
print("Lỗi chia 0")
except ValueError:
# Xử lý lỗi giá trị
print("Lỗi giá trị")
else:
# Chạy nếu KHÔNG có lỗi
print(f"Kết quả: {result}")
finally:
# Luôn luôn chạy
print("Hoàn thành!")
def divide(a, b):
if b == 0:
raise ValueError("Không thể chia cho 0!")
return a / b
try:
result = divide(10, 0)
except ValueError as e:
print(f"Lỗi: {e}")
try:
result = 10 / 0
except ZeroDivisionError:
print("Ghi log lỗi...")
raise # Ném lại exception để xử lý ở nơi khác

Tạo Exception riêng cho ứng dụng:

class AgeError(Exception):
"""Exception cho tuổi không hợp lệ"""
pass
def check_age(age):
if age < 0:
raise AgeError("Tuổi không thể âm!")
if age > 150:
raise AgeError("Tuổi quá lớn!")
return True
try:
check_age(-5)
except AgeError as e:
print(f"Lỗi tuổi: {e}")
def get_number(prompt):
while True:
try:
value = int(input(prompt))
return value
except ValueError:
print("Vui lòng nhập một số hợp lệ!")
age = get_number("Nhập tuổi: ")
print(f"Tuổi của bạn: {age}")
def read_file_safe(filename):
try:
with open(filename, 'r') as file:
content = file.read()
return content
except FileNotFoundError:
print(f"File '{filename}' không tồn tại!")
return None
except PermissionError:
print(f"Không có quyền đọc file '{filename}'!")
return None
except Exception as e:
print(f"Lỗi không xác định: {e}")
return None
content = read_file_safe("data.txt")
if content:
print(content)
def get_student_score(students, name):
try:
return students[name]
except KeyError:
return f"Học sinh '{name}' không tồn tại"
students = {"Alice": 95, "Bob": 87}
print(get_student_score(students, "Alice")) # 95
print(get_student_score(students, "Charlie")) # "Học sinh 'Charlie' không tồn tại"
def calculator():
while True:
try:
operation = input("Nhập phép tính (hoặc 'quit'): ")
if operation.lower() == 'quit':
break
result = eval(operation)
print(f"= {result}")
except ZeroDivisionError:
print("Lỗi: Không thể chia cho 0!")
except SyntaxError:
print("Lỗi: Cú pháp không đúng!")
except NameError:
print("Lỗi: Biến không tồn tại!")
except Exception as e:
print(f"Lỗi: {e}")
calculator()
def connect_to_server(max_retries=3):
for attempt in range(max_retries):
try:
print(f"Thử kết nối lần {attempt + 1}...")
# Giả lập kết nối
import random
if random.random() > 0.5:
raise ConnectionError("Kết nối thất bại")
print("Kết nối thành công!")
return True
except ConnectionError as e:
print(f"Lỗi: {e}")
if attempt == max_retries - 1:
print("Hết số lần thử!")
return False
return False
connect_to_server()
# TỐT
try:
number = int(input("Nhập số: "))
except ValueError:
print("Số không hợp lệ")
# TRÁNH
try:
number = int(input("Nhập số: "))
except:
print("Có lỗi")
# TỐT
try:
result = risky_operation()
except (ValueError, TypeError) as e:
handle_error(e)
# TRÁNH
try:
result = risky_operation()
except Exception:
pass # Nuốt tất cả lỗi - rất nguy hiểm!
try:
process_data()
except Exception as e:
print(f"Lỗi: {e}")
# Ghi log để debug sau
with open("error.log", "a") as log:
log.write(f"{datetime.now()}: {e}\n")
file = None
try:
file = open("data.txt", "r")
process(file)
except FileNotFoundError:
print("File không tồn tại")
finally:
if file:
file.close()
def process_user(user_id):
if not user_id:
raise ValueError("user_id không thể rỗng")
# Tiếp tục xử lý...

Cách tốt nhất để xử lý tài nguyên (file, connection):

# Tự động close file
try:
with open("data.txt", "r") as file:
content = file.read()
print(content)
except FileNotFoundError:
print("File không tồn tại")
# File tự động được đóng, ngay cả khi có lỗi

Sau khi học xong bài này, hãy thực hành với các bài tập sau: