67

ドキュメントによると、sys.exit() を呼び出すと SystemExit 例外が発生し、外部レベルでキャッチされる可能性があります。テストケース内から確実かつ疑いなく終了したい状況がありますが、unittest モジュールは SystemExit をキャッチし、終了を防ぎます。これは通常は素晴らしいことですが、私が対処しようとしている特定の状況は、テスト フレームワークが非テスト データベースを指すように構成されていることを検出した場合です。この場合、終了して、それ以上テストが実行されないようにしたいと考えています。もちろん、単体テストは SystemExit をトラップし、順調に進んでいるため、私を妨害しています。

私がこれまでに考えた唯一のオプションは、ctypes または exit(3) を直接呼び出すのに似たものを使用することですが、これは本当に単純であるべき何かに対するかなり厄介なハックのようです。

4

3 に答える 3

99

os._exit()例外をスローせずに、直接終了するように呼び出すことができます。

import os
os._exit(1)

これにより、モジュールなどのすべての python シャットダウン ロジックがバイパスさatexitれ、この状況で回避しようとしている例外処理ロジックは実行されません。引数は、プロセスによって返される終了コードです。

于 2008-10-06T06:24:53.900 に答える
61

ジェルブが言ったように、os._exit(1)あなたの答えです。ただし、ブロック、ファイルのクローズなどを含むすべてのクリーンアップ手順をバイパスすることを考えると、絶対finally:に避けるべきです。では、より安全な(っぽい)使用方法を提示できますか?

問題がSystemExit外側のレベル (つまり、単体テスト) で捕捉されている場合は、自分が外側のレベルになります。メイン コードをtry/exceptブロックで囲み、 catchSystemExitを呼び出しos._exit()て、そこでのみ呼び出します。このようsys.exitにして、通常はコードのどこからでも呼び出すことができ、トップ レベルにバブル アウトし、すべてのファイルを適切に閉じてすべてのクリーンアップを実行し、次にを呼び出しos._exitます。

どの出口が「緊急」出口であるかを選択することもできます。以下のコードは、そのようなアプローチの例です。

import sys, os

EMERGENCY = 255  # can be any number actually

try:
    # wrap your whole code here ...
    # ... some code
    if x: sys.exit()
    # ... some more code
    if y: sys.exit(EMERGENCY)  # use only for emergency exits
    ...  # yes, this is valid python!

    # Might instead wrap all code in a function
    # It's a common pattern to exit with main's return value, if any
    sys.exit(main())

except SystemExit as e:
    if e.code != EMERGENCY:
        raise  # normal exit, let unittest catch it at the outer level
else:
    os._exit(EMERGENCY)  # try to stop *that*!

e.code一部の読者が気付いていないことについては、すべての組み込み例外の属性と同様に文書化されています。

于 2012-12-05T12:23:15.827 に答える
0

quit を使用することもできます。以下の例を参照してください。

while True:
print('Type exit to exit.')
response = input()
if response == 'exit':
    quit(0)
print('You typed ' + response + '.')
于 2020-05-20T21:18:30.267 に答える