皆さんご存知Python3。Python3には、意外とexit関数にあたるものが多いです。今回は、これらを紹介して、使い分けについて話していこうと思います。

TL;DR

  • exit() ← 対話型インタプリタで使うべき
  • quit()exit()と同じ
  • sys.exit() ← 普通のスクリプトで使うべき
  • os._exit() ← 子プロセスの終了に使うべき
  • raise SystemExit ←使わないべき

使い分け

exit(code: Optional[int|Any] = None), quit(code: Optional[int|Any] = None)[fn]引数に終了コードまたはエラーコードを受け取る。終了コード(int)を受け取ると、そのステータスで終了する。Noneを受け取ると、1と解釈される。intではないエラーコードを受け取ると、基本的にはそのオブジェクトをエラーコードとして標準エラー出力に出力し、ステータス1で異常終了する。詳しくはsysモジュールのドキュメントを参照。[/fn]

どちらも_sitebuiltins.Quitterオブジェクトで、site.main()を実行する、もしくはPython3インタプリタを-Sオプションなしで起動することで自動的に定義されます。

公式ドキュメントには、この2つを含めた「siteモジュールによって定義される定数」について、

They are useful for the interactive interpreter shell and should not be used in programs.

https://docs.python.org/3/library/constants.html

と言及し、インタラクティブシェルでのみの使用を推奨しています。そのため、モジュールやスクリプトにてこの2つを使用することは控えたほうが良さそうです。

sys.exit(code: Optional[int|Any] = None)[fn]ref:1[/fn]

builtin_function_or_methodオブジェクト。sysモジュールをインポートすると使えるようになります。

SystemExit例外(後述)を送出します。モジュールやスクリプトでは基本的にこの関数を使用して終了させます。理由としては、公式ドキュメントには

Since exit() ultimately “only” raises an exception, it will only exit the process when called from the main thread, and the exception is not intercepted. Cleanup actions specified by finally clauses of try statements are honored, and it is possible to intercept the exit attempt at an outer level.

https://docs.python.org/3/library/sys.html

とありますが、内部では結局_sitebuiltins.Quitterとほとんど同じ処理をしている[fn]みんなだいすきstack overflowにて参考になる回答が載っています。[/fn]ので、そこまで違いはなさそうです。

os._exit(n: int)

sys.exitと同じく、builtin_function_or_methodオブジェクト。osモジュールをインポートすると使えるようになります。

SystemExit例外の送出ではなく、C言語の_exit()関数が直接呼び出されます。そのため、クリーンアップ処理や、標準入出力バッファのフラッシュは行われません。os.fork()された子プロセスの終了や、緊急終了に使うべきで、通常のモジュール、スクリプト、インタラクティブシェルでは使用されるべきではありません。

引数nは終了コードで、他とは違い必須となっています。また、intしか受け付けません。int以外の引数が渡された場合、TypeError例外が送出されます。

raise SystemExit(code: Optional[int|Any] = None)[fn]ref:1[/fn]

os._exit()を除く全てのexit関数が共通して呼び出す、「インタプリタを終了させる」という例外SystemExitを送出されます。

SystemExit例外は、送出されてもエラーとして扱われずに、クリーンアップ処理などを行ってからインタプリタを終了させる例外です。

確かにSystemExitを送出するとインタプリタが終了しますが、明らかに他の選択肢よりもパイソニック[ref]Pythonらしい、きれいで読みやすいコードのこと。[/ref]な書き方ではないので控えたほうが良さそうです。

まとめ(?)

TL;DRに書いた通り、普段はsys.exit()を使用するのが良さそうです。
ちなみに、sys.exit_sitebuiltins.Quitterが送出するSystemExit例外はBaseException例外を継承した例外として扱えるので、

import sys
try:
    sys.exit()
except SystemExit:
    ...
    raise

みたいにすると、sys.exit()などのSystemExit例外を用いた終了を無視させたり、終了する前に独自のクリーンアップ処理を行わせることができます。状況に応じて、応用してみてください。

投稿者 okaits#7534

okaits#7534です。コンピュータ関連と合成音声が趣味です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です