Học bằng cách đọc theo thứ tự

Phát sinh ngoại lệ với raise / Lớp ngoại lệ tùy chỉnh

Học cách ném ngoại lệ riêng trong Python với raise và định nghĩa lớp Exception tùy chỉnh để xử lý lỗi chính xác.

Trong bài trước về try / except, chúng ta đã xem phía nhận của một ngoại lệ.

Bài này nói về raisephía phát sinh, nơi bạn tự phơi bày một ngoại lệ. Khi bạn phát sinh ngoại lệ khi đầu vào không hợp lệ hoặc trạng thái không mong đợi, bên gọi được đảm bảo nhận biết qua try / except.

Cơ bản về raise

Viết raise ExceptionClass("thông điệp") phát sinh ngoại lệ đó ngay lúc đó. Ngay khoảnh khắc raise thực thi, phần còn lại của code bị bỏ qua và điều khiển nhảy đến except khớp.

Thông điệp là tùy chọn, nhưng bao gồm lý do nó thất bại cho phép bên nhận đọc nó ra qua except ... as e.

Luồng raise → except
chạy thân tryraise ValueError("...")(phần còn lại try bị bỏ)except ValueError as ee nhận thông điệptiếp tục chạynhảy
# Phát sinh một ValueError và bắt nó ở phía nhận
try:
    raise ValueError("Tuổi không hợp lệ")
    print("không bao giờ đến")
except ValueError as e:
    print(f"Đã bắt: {e}")
# Kết quả: Đã bắt: Tuổi không hợp lệ

# Mọi ngoại lệ có sẵn đều dùng được nguyên
# Các lỗi phổ biến: ValueError / TypeError / KeyError / IndexError

Thực hiện chuyến đi nhỏ nhất của raisetry / except.

① Bên trong try, chạy raise KeyError("user_id không tìm thấy").

② Bắt nó bằng except KeyError as e: và in "Loại: KeyError / Chi tiết: {e}" trên một dòng.

③ Sau try / except, gọi print("Tiếp tục…") để xác nhận chương trình không dừng lại.

(Phần giải thích sẽ hiện ra khi bạn chạy code đúng.)

Python Editor

Chạy code để xem đầu ra

Kiểm tra dữ liệu với if + raise

raise được dùng thường xuyên nhất cho kiểm tra đầu vào. Khi một if phát hiện thứ gì đó không hợp lệ, ngay lập tức raise và trả lời gọi về cho bên gọi. Đây là kỹ thuật chuẩn trong hàm (sẽ học sau), nơi phát sinh bên trong một hàm thông báo cho bên gọi về đối số không hợp lệ.

Luồng — đường bình thường chạy qua; đường bất thường phát sinh và dừng — là mẫu cốt lõi cho kiểm tra trong code production.

Luồng kiểm tra với if + raise
nhận đầu vàođk 1: giátrị không hợp lệ?raise ValueError(...)đk 2: kiểukhông hợp lệ?raise TypeError(...)đã qua mọi kiểm trachạy xử lý bình thườngexcept của bên gọi bắt nóKhôngKhông

Kiểm tra đầu vào từng điều kiện một; ngay khoảnh khắc điều gì đó thất bại, raise và dừng. Chỉ khi mọi điều kiện đều qua thì xử lý bình thường mới tiếp tục. Vì raise đầu tiên thắng, thứ tự các kiểm tra đặt ra độ ưu tiên của chúng.

# Kiểm tra giá sản phẩm: 0 hoặc thấp hơn là lỗi
price = -500

try:
    if price < 0:
        raise ValueError(f"Giá phải là 0 trở lên (nhận được: {price})")
    if not isinstance(price, int):
        raise TypeError(f"Giá phải là số nguyên (kiểu nhận được: {type(price).__name__})")
    print(f"Đã đăng ký: {price}")
except ValueError as e:
    print(f"Lỗi giá trị: {e}")
except TypeError as e:
    print(f"Lỗi kiểu: {e}")
# Kết quả: Lỗi giá trị: Giá phải là 0 trở lên (nhận được: -500)

Hướng dẫn sơ bộ về chọn ngoại lệ có sẵn nào để raise: dùng ValueError khi giá trị sai, TypeError khi loại (kiểu) không khớp với điều mong đợi, và KeyError / IndexError khi khóa hoặc phần tử đích không tồn tại trong dict hoặc list.

Kiểm tra tên người dùng.

① Định nghĩa user_name = "".

② Bên trong try, phát sinh ValueError("Tên người dùng là bắt buộc") khi user_name là chuỗi rỗng, và ValueError("Tên người dùng phải từ 20 ký tự trở xuống") khi len(user_name) > 20. Nếu cả hai đều không đúng, in "Đã đăng ký: {user_name}".

③ Bắt bằng except ValueError as e: và in "Lỗi đầu vào: {e}".

Python Editor

Chạy code để xem đầu ra

Định nghĩa lớp ngoại lệ tùy chỉnh

Ngoại lệ có sẵn một mình đôi khi khiến khó biết kiểm tra nào đã thất bại. Định nghĩa lớp ngoại lệ của riêng bạn cho phép bạn bắt nó chính xác ở phía except.

Hình dạng là class ErrorName(Exception): với pass (rỗng) làm thân — thế thôi. Chúng ta sẽ học sâu về lớp trong chương lập trình hướng đối tượng sắp tới, nhưng với lớp ngoại lệ, một dòng này là đủ.

Định nghĩa và dùng lớp ngoại lệ tùy chỉnh
Exception(cha có sẵn)class OutOfStockError(Exception): passraise OutOfStockError("hết hàng")except OutOfStockError as e:lấy thông báo từ etiếp tục chạyđặt làm lớp cha (định nghĩa)dùng kiểu
# Định nghĩa một ngoại lệ tùy chỉnh (1 dòng là đủ)
class InvalidAgeError(Exception):
    pass

class DuplicateUserError(Exception):
    pass

registered_users = ["minh", "linh"]
new_user = "minh"
new_age = -1

try:
    if new_age < 0:
        raise InvalidAgeError(f"Tuổi phải là 0 trở lên: {new_age}")
    if new_user in registered_users:
        raise DuplicateUserError(f"Đã đăng ký: {new_user}")
    print(f"Đã đăng ký: {new_user}")
except InvalidAgeError as e:
    print(f"Lỗi tuổi: {e}")
except DuplicateUserError as e:
    print(f"Lỗi trùng lặp: {e}")
# Kết quả: Lỗi tuổi: Tuổi phải là 0 trở lên: -1

Ngoại lệ tùy chỉnh đặt Exception làm lớp cha

Exception trong dấu ngoặc đơn chỉ định lớp cha. Đặt Exception ở đó nghĩa là lớp tùy chỉnh của bạn tự động có được các tính năng ngoại lệ tiêu chuẩn — nó có thể mang theo thông điệp, có thể bị bắt bởi except Exception chung, v.v. Bản thân cơ chế cha / con (kế thừa) sẽ được học trong chương lập trình hướng đối tượng, nhưng chỉ một dòng này là đủ để định nghĩa một ngoại lệ.

Làm một ngoại lệ "hết hàng" chuyên dụng và phát sinh nó trong một quy trình mua hàng.

① Định nghĩa class OutOfStockError(Exception): pass.

② Thiết lập stock = {"táo": 3, "bánh mì": 0}want = "bánh mì".

③ Trong try, khi stock[want] == 0, phát sinh OutOfStockError(f"Hết hàng: {want}"); ngược lại in "Đã mua: {want}".

④ Bắt bằng except OutOfStockError as e: và in "Thông báo: {e}".

Python Editor

Chạy code để xem đầu ra

Trong bài này bạn đã học cách tự phát sinh ngoại lệ với raise, mẫu if + raise cho kiểm tra dữ liệu, và cách định nghĩa lớp ngoại lệ tùy chỉnh đặt Exception làm lớp cha.

Tiếp theo, chúng ta sẽ xem xét def — thứ đã xuất hiện vài lần rồi — như một chủ đề chính và học cách gói gọn và tái sử dụng logic với hàm.

QUIZ

Kiểm tra kiến thức

Hãy trả lời từng câu hỏi một.

Câu 1Đoạn code sau in gì?
try:
raise ValueError("NG")
print("A")
except ValueError as e:
print(e)
print("B")

Câu 2Ngoại lệ có sẵn nào là phù hợp nhất khi giá trị không hợp lệ?

Câu 3Lợi ích lớn nhất của việc dùng ngoại lệ tùy chỉnh class MyError(Exception): pass là gì?