Python - Exception Chaining

Exception Chaining

Chuỗi ngoại lệ là một kỹ thuật xử lý ngoại lệ bằng cách ném lại một ngoại lệ đã bị bắt sau khi bọc nó bên trong một ngoại lệ mới. Ngoại lệ gốc được lưu trữ như một thuộc tính (chẳng hạn như nguyên nhân) của ngoại lệ mới.

Trong quá trình xử lý một ngoại lệ 'A', có thể xảy ra một ngoại lệ khác 'B'. Việc biết về cả hai ngoại lệ này là hữu ích để gỡ lỗi vấn đề. Đôi khi, một bộ xử lý ngoại lệ có thể cố ý ném lại một ngoại lệ, hoặc để cung cấp thêm thông tin hoặc để chuyển đổi một ngoại lệ sang loại khác.

Trong Python 3.x, có thể thực hiện chuỗi ngoại lệ. Nếu có bất kỳ ngoại lệ nào không được xử lý bên trong một phần except, nó sẽ được gắn với ngoại lệ đang được xử lý và được bao gồm trong thông báo lỗi.

Example

Trong đoạn mã sau, việc cố gắng mở một tệp không tồn tại sẽ gây ra lỗi FileNotFoundError. Lỗi này sẽ được phát hiện bởi khối except. Trong quá trình xử lý, một lỗi khác sẽ được phát sinh.

try:
   open("nofile.txt")
except OSError:
   raise RuntimeError("unable to handle error")

Nó sẽ tạo ra output

Traceback (most recent call last):
  File "/home/cg/root/64afcad39c651/main.py", line 2, in <module>
open("nofile.txt")
FileNotFoundError: [Errno 2] No such file or directory: 'nofile.txt'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/cg/root/64afcad39c651/main.py", line 4, in <module>
    raise RuntimeError("unable to handle error")
RuntimeError: unable to handle error

The raise . . from Statement

Nếu bạn sử dụng một câu lệnh from tùy chọn trong câu lệnh raise, nó cho thấy rằng một ngoại lệ là hậu quả trực tiếp của một ngoại lệ khác. Điều này có thể hữu ích khi bạn đang chuyển đổi các ngoại lệ. Đối tượng sau từ khóa from nên là đối tượng ngoại lệ.

try:
   open("nofile.txt")
except OSError as exc:
   raise RuntimeError from exc

Nó sẽ tạo ra output

Traceback (most recent call last):
  File "/home/cg/root/64afcad39c651/main.py", line 2, in <module>
    open("nofile.txt")
FileNotFoundError: [Errno 2] No such file or directory: 'nofile.txt'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/cg/root/64afcad39c651/main.py", line 4, in <module>
    raise RuntimeError from exc
RuntimeError

The raise . . from None Statement

Nếu chúng ta sử dụng None trong câu lệnh from thay vì đối tượng ngoại lệ, thì chuỗi ngoại lệ tự động mà đã được tìm thấy trong ví dụ trước đó sẽ bị vô hiệu hóa.

try:
   open("nofile.txt")
except OSError as exc:
   raise RuntimeError from None

Nó sẽ tạo ra output

Traceback (most recent call last):
 File "C:\Python311\hello.py", line 4, in <module>
  raise RuntimeError from None
RuntimeError

The __context__ and __cause__ Expression

Việc nâng cao một ngoại lệ trong khối except sẽ tự động thêm ngoại lệ đã được bắt vào thuộc tính __context__ của ngoại lệ mới. Tương tự, bạn cũng có thể thêm __cause__ vào bất kỳ ngoại lệ nào bằng cách sử dụng cú pháp raise ... from .

try:
   try:
      raise ValueError("ValueError")
   except ValueError as e1:
      raise TypeError("TypeError") from e1
except TypeError as e2:
   print("The exception was", repr(e2))
   print("Its __context__ was", repr(e2.__context__))
   print("Its __cause__ was", repr(e2.__cause__))

Nó sẽ tạo ra output

The exception was TypeError('TypeError')
Its __context__ was ValueError('ValueError')
Its __cause__ was ValueError('ValueError')