try-except-else存在的原因是什么?
一个try
块可以处理预期的错误。该except
块应该只捕获您准备处理的异常。如果您处理了意外错误,则您的代码可能会做错事情并隐藏错误。
else
如果没有错误,将执行一个子句,通过不执行该代码try
块中的代码,可以避免捕获意外错误。同样,捕获意外错误可能会隐藏错误。
例
例如:
try:
try_this(whatever)
except SomeException as the_exception:
handle(the_exception)
else:
return something
“ try,except”套件有两个可选子句,else
和finally
。所以实际上是try-except-else-finally
。
else
仅在try
块中没有异常的情况下才会评估。它使我们能够简化下面更复杂的代码:
no_error = None
try:
try_this(whatever)
no_error = True
except SomeException as the_exception:
handle(the_exception)
if no_error:
return something
因此,如果将a else
与替代方案(可能会产生错误)进行比较,我们会发现它减少了代码行,并且我们可以拥有更具可读性,可维护性和更少错误的代码库。
finally
finally
即使使用return语句对另一行进行评估,它也将执行。
用伪代码分解
这可能有助于以尽可能小的形式展示所有功能并带有注释来分解此内容。假定此语法在语法上正确(但除非定义名称,否则不可运行)伪代码在函数中。
例如:
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
的确,我们可以将代码包含在else
块中的代码中try
,如果没有异常,它将在其中运行,但是如果该代码本身引发了我们正在捕获的异常,该怎么办?将其留在try
块中将隐藏该错误。
我们希望最小化try
块中的代码行,以避免捕获我们未曾想到的异常,其原理是,如果我们的代码失败,我们希望它大声失败。这是最佳做法。
据我了解,异常不是错误
在Python中,大多数例外都是错误。
我们可以使用pydoc查看异常层次结构。例如,在Python 2中:
$ python -m pydoc exceptions
或Python 3:
$ python -m pydoc builtins
将给我们层次结构。我们可以看到大多数Exception
错误都是错误的,尽管Python使用其中的一些错误来结束for
循环(StopIteration
)。这是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
有评论者问:
假设您有一个可对外部API进行ping的方法,并且想在API包装器之外的类上处理异常,那么您是否只是从方法中的except子句中返回e,其中e是异常对象?
不,您不返回该异常,只需将其重新引发raise
以保留堆栈跟踪即可。
try:
try_this(whatever)
except SomeException as the_exception:
handle(the_exception)
raise
或者,在Python 3中,您可以引发新的异常并通过异常链接保留回溯:
try:
try_this(whatever)
except SomeException as the_exception:
handle(the_exception)
raise DifferentException from the_exception
我在这里详细回答。