Jupyternotebookのセルにsys.exit() を入れて処理が不安定になった話
ファイルやAPI呼び出ししたJSON形式のデータを加工していた際に、既存のPython スクリプトから加工用の関数を持ってきて使っておりましたら、どうも重複データが発生していたりと、元ネタのチェックを含めて確認していたところ、加工処理をデバッグprintを追加して実行させておったら、コード中は処理順が
STEP1 –
STEP1 END
STEP2
STEP2 END
STEP3
…
と書いてあるところ、実行ログを見ると
STEP1
STEP2
STEP2 END
STEP2
STEP2 END
STEP1 END
…
となっていて、頭を抱えておったわけです。シンプルに逐次処理をさせているだけなのに、なぜに処理が前後するのか訳が分からないわけです。記録を見ればSTEP2で作成しているレコードが重複してしまうわけで、そこの謎が解けたわけですが、ループどころか制御文が入っていないのになぜ処理がループするのか謎でした。
各ステップでは別の動作中のスクリプトから関数を持ってきて処理をさせておったわけですが、そこに含まれていた sys.exit() がアヤシイ感じでした。
コードをGPT-5に食わせて、原因を聞いてみますと次のようなご神託が。
Jupyter Notebook で sys.exit() を使うと、SystemExit 例外が発生し、通常は「そのセルの実行が中断」されます。しかし、for ループや関数呼び出しの中で sys.exit() が発生した場合、例外がうまく伝播しないことがあります。
特に Notebook では、セルの実行が「内部的に try-except でラップ」されているため、sys.exit() の例外が完全にカーネルを終了せず、セルの実行が途中で止まったり、部分的に残った処理が再度実行されたりすることがあります。
その結果、以下のような現象が起こります:
sys.exit() で一度止まったはずの処理が、セルの再実行やループの途中で再度呼ばれる
print文の出力順序が乱れる(STEP1, STEP2, STEP2, STEP1 END など)
ループや関数の中で例外がキャッチされていると、処理が繰り返される
これは、Notebook のセル実行が「Pythonスクリプトの実行」とは異なり、カーネル全体を終了しないため、例外の伝播や状態管理が複雑になるためです。対策:
Notebook では sys.exit() の使用を避け、return や raise Exception で明示的に処理を止める方が安全です。
sys.exit() を使う場合は、例外がどこでキャッチされるか、ループや関数の外に正しく伝播するかを確認してください。
この現象は Notebook 特有のものです。通常の Python スクリプトでは起こりません。
本来あるはずの指定の条件のデータが見つからなかった場合に、sys.exit() を呼び出してスクリプトを止めていたわけですが、実行ログを見るとこの個所は呼び出されていなかったわけですが、sys.exit() をコメントアウトして再実行してみると、確かに STEP1, STEP2, STEP3, … と淡々と正常に処理されていくわけです。
例外をキャッチして sys.exit() が呼ばれて処理が不安定になるなら分かるのですが、これが書いてあるだけで、処理が不安定になるとか意味が分かりません。ぐぬぬ。
いずれにせよ、Jupyter Notebookでのsys.exit() が呪いの言葉だと分かったので、ご神託の通りに raise Exceptionなどで書き換えて、処理が流れるところまで確認できました。
クソ忙しいので深堀できませんでしたが、なんなのこれ。

