Câu trả lời cho câu hỏi này phụ thuộc vào phiên bản Python bạn đang sử dụng.
Trong Python 3
Thật đơn giản: các trường hợp ngoại lệ được trang bị một __traceback__
thuộc tính có chứa dấu vết. Thuộc tính này cũng có thể ghi và có thể được thiết lập thuận tiện bằng cách sử dụng with_traceback
phương thức ngoại lệ:
raise Exception("foo occurred").with_traceback(tracebackobj)
Các tính năng này được mô tả tối thiểu như một phần của raise
tài liệu.
Tất cả tín dụng cho phần này của câu trả lời sẽ thuộc về Vyctor, người đầu tiên đăng thông tin này . Tôi chỉ đưa nó vào đây vì câu trả lời này bị kẹt ở trên cùng và Python 3 đang trở nên phổ biến hơn.
Trong Python 2
Nó phức tạp một cách khó chịu. Rắc rối với tracebacks là chúng có các tham chiếu đến các khung ngăn xếp và các khung ngăn xếp có các tham chiếu đến các truy nguyên có tham chiếu đến các khung ngăn xếp có tham chiếu đến ... bạn có thể hiểu được. Điều này gây ra vấn đề cho bộ thu gom rác. (Cảm ơn ecatmur vì lần đầu tiên chỉ ra điều này.)
Cách tốt nhất để giải quyết vấn đề này là phá vỡ chu kỳ sau khi rời khỏi except
mệnh đề, đó là những gì Python 3 làm. Giải pháp Python 2 xấu hơn nhiều: bạn được cung cấp một hàm đặc biệt sys.exc_info()
, chỉ hoạt động bên trong except
mệnh đề . Nó trả về một bộ giá trị chứa ngoại lệ, kiểu ngoại lệ và truy xuất cho bất kỳ ngoại lệ nào hiện đang được xử lý.
Vì vậy, nếu bạn đang ở bên trong except
mệnh đề, bạn có thể sử dụng đầu ra của sys.exc_info()
cùng với traceback
mô-đun để làm những việc hữu ích khác nhau:
>>> import sys, traceback
>>> def raise_exception():
... try:
... raise Exception
... except Exception:
... ex_type, ex, tb = sys.exc_info()
... traceback.print_tb(tb)
... finally:
... del tb
...
>>> raise_exception()
File "<stdin>", line 3, in raise_exception
Nhưng khi chỉnh sửa của bạn cho thấy, bạn đang cố gắng để có được những traceback rằng sẽ đã được in nếu ngoại trừ của bạn đã không được xử lý, sau khi nó đã đã được xử lý. Đó là một câu hỏi khó hơn nhiều. Thật không may, sys.exc_info
trả về (None, None, None)
khi không có ngoại lệ nào được xử lý. Các sys
thuộc tính liên quan khác cũng không giúp được gì. sys.exc_traceback
không được chấp nhận và không được xác định khi không có ngoại lệ nào được xử lý; sys.last_traceback
có vẻ hoàn hảo, nhưng nó dường như chỉ được xác định trong các phiên tương tác.
Nếu bạn có thể kiểm soát cách đặt ngoại lệ, bạn có thể sử dụng inspect
và một ngoại lệ tùy chỉnh để lưu trữ một số thông tin. Nhưng tôi không hoàn toàn chắc chắn điều đó sẽ hoạt động như thế nào.
Nói thật, việc bắt và trả lại một ngoại lệ là một việc không bình thường. Đây có thể là một dấu hiệu cho thấy bạn cần phải cấu trúc lại.