Python のあらゆる try-finally ブロックでは、そのfinally
ブロックが常に実行されることが保証されていますか?
たとえば、except
ブロック内で return するとします。
try:
1/0
except ZeroDivisionError:
return
finally:
print("Does this code run?")
あるいは、 をリレイズするかもしれませんException
:
try:
1/0
except ZeroDivisionError:
raise
finally:
print("What about this code?")
テストではfinally
上記の例が実行されることが示されていますが、私が考えていない他のシナリオもあると思います。
finally
Python でブロックの実行が失敗するシナリオはありますか?
ベストアンサー1
「保証」という言葉は、 のどの実装にもふさわしいものよりはるかに強い言葉です。保証されているのは、実行が-構造finally
全体から流れ出る場合、それを実行するには を通過するということです。保証されていないのは、実行が-から流れ出ることです。try
finally
finally
try
finally
finally
ジェネレータまたは非同期コルーチン内のA は実行されない可能性がありますオブジェクトが最後まで実行されない場合。これが発生する原因は多数考えられますが、その 1 つを次に示します。def gen(text): try: for line in text: try: yield int(line) except: # Ignore blank lines - but catch too much! pass finally: print('Doing important cleanup') text = ['1', '', '2', '', '3'] if any(n > 1 for n in gen(text)): print('Found a number') print('Oops, no cleanup.')
この例は少しトリッキーであることに注意してください。ジェネレータがガベージ コレクションされると、Python は例外
finally
をスローしてブロックを実行しようとしますGeneratorExit
が、ここではその例外をキャッチしてからyield
再度キャッチし、その時点で Python は警告 ("generator ignore GeneratorExit") を出力して処理を中止します。PEP 342 (拡張ジェネレータによるコルーチン)詳細については。ジェネレーターまたはコルーチンが最後まで実行されない可能性があるその他の状況としては、オブジェクトが GC されない場合 (はい、CPython でも可能です)、
async with
await
内の sの場合__aexit__
、またはオブジェクトがブロック内のawait
s またはs の場合などがあります。このリストは網羅的なものではありません。yield
finally
finally
デーモンスレッド内のAは実行されない可能性があるデーモン以外のスレッドがすべて最初に終了した場合。os._exit
直ちにプロセスを停止しますブロックを実行せずにfinally
。os.fork
finally
ブロックを引き起こす可能性があります実行する2回2回発生すると予想される通常の問題だけでなく、共有リソースへのアクセスが適切に行われていない場合、同時アクセスの競合(クラッシュ、停止など)が発生する可能性があります。正しく同期。multiprocessing
ワーカープロセスを作成するためにfork-without-execを使用するので、フォーク開始方法(Unix のデフォルト)、os._exit
ワーカーのジョブが完了するとワーカーを呼び出しますが、finally
相互multiprocessing
作用が問題になることがあります (例)。- C レベルのセグメンテーション エラーにより、
finally
ブロックの実行が妨げられます。 kill -SIGKILL
ブロックの実行を防止しますfinally
。SIGTERM
およびも、シャットダウンを自分で制御するハンドラーをインストールしない限り、ブロックの実行をSIGHUP
防止します。デフォルトでは、Python はまたは を処理しません。finally
SIGTERM
SIGHUP
- の例外により
finally
クリーンアップが完了できない場合があります。特に注目すべきケースは、ユーザーがコントロール+Cを押した場合です。ただブロックの実行を開始するとfinally
、Python は を発生させKeyboardInterrupt
、ブロックの内容の各行をスキップしますfinally
。(KeyboardInterrupt
-safe コードを書くのは非常に困難です)。 - コンピュータの電源が切れたり、休止状態になって起動しなくなったりすると、
finally
ブロックは実行されません。
ブロックfinally
はトランザクション システムではありません。アトミック性の保証などは一切提供されません。これらの例のいくつかは明白に思えるかもしれませんが、そのようなことが起こる可能性があることを忘れ、finally
過度に頼りにしがちです。