Lý do cho sự cố gắng ngoại trừ tồn tại là gì?
Một try
khối cho phép bạn xử lý một lỗi dự kiến. Các except
khối chỉ nên bắt ngoại lệ bạn đang chuẩn bị để xử lý. Nếu bạn xử lý một lỗi không mong muốn, mã của bạn có thể làm sai và ẩn lỗi.
Một else
mệnh đề sẽ thực thi nếu không có lỗi và bằng cách không thực thi mã đó trong try
khối, bạn tránh gặp lỗi không mong muốn. Một lần nữa, bắt một lỗi không mong muốn có thể ẩn lỗi.
Thí dụ
Ví dụ:
try:
try_this(whatever)
except SomeException as the_exception:
handle(the_exception)
else:
return something
Bộ "thử, ngoại trừ" có hai mệnh đề tùy chọn else
và finally
. Vì vậy, nó thực sự try-except-else-finally
.
else
sẽ chỉ đánh giá nếu không có ngoại lệ từ try
khối. Nó cho phép chúng tôi đơn giản hóa mã phức tạp hơn dưới đây:
no_error = None
try:
try_this(whatever)
no_error = True
except SomeException as the_exception:
handle(the_exception)
if no_error:
return something
Vì vậy, nếu chúng ta so sánh với một else
giải pháp thay thế (có thể tạo ra lỗi), chúng ta sẽ thấy rằng nó làm giảm các dòng mã và chúng ta có thể có một cơ sở mã dễ đọc hơn, dễ bảo trì hơn và ít lỗi hơn.
finally
finally
sẽ thực thi bất kể điều gì, ngay cả khi một dòng khác đang được đánh giá bằng câu lệnh return.
Bị hỏng với mã giả
Nó có thể giúp phá vỡ điều này, ở dạng nhỏ nhất có thể thể hiện tất cả các tính năng, với các bình luận. Giả sử điều này đúng về mặt cú pháp (nhưng không thể chạy được trừ khi tên được xác định) mã giả nằm trong một hàm.
Ví dụ:
try:
try_this(whatever)
except SomeException as the_exception:
handle_SomeException(the_exception)
# Handle a instance of SomeException or a subclass of it.
except Exception as the_exception:
generic_handle(the_exception)
# Handle any other exception that inherits from Exception
# - doesn't include GeneratorExit, KeyboardInterrupt, SystemExit
# Avoid bare `except:`
else: # there was no exception whatsoever
return something()
# if no exception, the "something()" gets evaluated,
# but the return will not be executed due to the return in the
# finally block below.
finally:
# this block will execute no matter what, even if no exception,
# after "something" is eval'd but before that value is returned
# but even if there is an exception.
# a return here will hijack the return functionality. e.g.:
return True # hijacks the return in the else clause above
Đúng là chúng ta có thể bao gồm mã trong else
khối trong try
khối thay vào đó, nơi nó sẽ chạy nếu không có ngoại lệ, nhưng điều gì xảy ra nếu chính mã đó phát sinh ngoại lệ của loại chúng ta đang bắt? Để nó trong try
khối sẽ che giấu lỗi đó.
Chúng tôi muốn giảm thiểu các dòng mã trong try
khối để tránh bắt ngoại lệ mà chúng tôi không mong đợi, theo nguyên tắc là nếu mã của chúng tôi thất bại, chúng tôi muốn nó thất bại lớn. Đây là một thực hành tốt nhất .
Theo hiểu biết của tôi, ngoại lệ không phải là lỗi
Trong Python, hầu hết các ngoại lệ là lỗi.
Chúng ta có thể xem hệ thống phân cấp ngoại lệ bằng cách sử dụng pydoc. Ví dụ: trong Python 2:
$ python -m pydoc exceptions
hoặc Python 3:
$ python -m pydoc builtins
Sẽ cho chúng ta thứ bậc. Chúng ta có thể thấy rằng hầu hết các loại Exception
là lỗi, mặc dù Python sử dụng một số trong số chúng cho những thứ như for
vòng lặp kết thúc ( StopIteration
). Đây là hệ thống phân cấp của Python 3:
BaseException
Exception
ArithmeticError
FloatingPointError
OverflowError
ZeroDivisionError
AssertionError
AttributeError
BufferError
EOFError
ImportError
ModuleNotFoundError
LookupError
IndexError
KeyError
MemoryError
NameError
UnboundLocalError
OSError
BlockingIOError
ChildProcessError
ConnectionError
BrokenPipeError
ConnectionAbortedError
ConnectionRefusedError
ConnectionResetError
FileExistsError
FileNotFoundError
InterruptedError
IsADirectoryError
NotADirectoryError
PermissionError
ProcessLookupError
TimeoutError
ReferenceError
RuntimeError
NotImplementedError
RecursionError
StopAsyncIteration
StopIteration
SyntaxError
IndentationError
TabError
SystemError
TypeError
ValueError
UnicodeError
UnicodeDecodeError
UnicodeEncodeError
UnicodeTranslateError
Warning
BytesWarning
DeprecationWarning
FutureWarning
ImportWarning
PendingDeprecationWarning
ResourceWarning
RuntimeWarning
SyntaxWarning
UnicodeWarning
UserWarning
GeneratorExit
KeyboardInterrupt
SystemExit
Một bình luận hỏi:
Giả sử bạn có một phương thức ping API bên ngoài và bạn muốn xử lý ngoại lệ tại một lớp bên ngoài trình bao bọc API, bạn có đơn giản trả lại e từ phương thức theo mệnh đề ngoại trừ trong đó e là đối tượng ngoại lệ không?
Không, bạn không trả lại ngoại lệ, chỉ cần chỉnh lại nó bằng một khoảng trống raise
để bảo toàn stacktrace.
try:
try_this(whatever)
except SomeException as the_exception:
handle(the_exception)
raise
Hoặc, trong Python 3, bạn có thể đưa ra một ngoại lệ mới và duy trì backtrace với chuỗi ngoại lệ:
try:
try_this(whatever)
except SomeException as the_exception:
handle(the_exception)
raise DifferentException from the_exception
Tôi giải thích trong câu trả lời của tôi ở đây .