try-except-else が存在する理由は何ですか?
try
ブロックを使用すると、予想されるエラーを処理できます。ブロックは、except
処理する準備ができている例外のみをキャッチする必要があります。予期しないエラーを処理すると、コードが間違った動作をしてバグが隠れる可能性があります。
else
エラーがなければ句が実行され、ブロック内でそのコードを実行しないことで、予期try
しないエラーのキャッチを回避できます。繰り返しになりますが、予期しないエラーをキャッチすると、バグが隠れる可能性があります。
例
例えば:
try:
try_this(whatever)
except SomeException as the_exception:
handle(the_exception)
else:
return something
「try, except」スイートには、2 つの省略可能な句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
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 ラッパーの外部のクラスで例外を処理したいとします。e が例外オブジェクトである except 節の下でメソッドから単に 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
ここで私の答えを詳しく説明します。