web-dev-qa-db-ja.com

プログラムのシャットダウン中にPythonでKeyboardInterruptをキャッチ

私はPythonでコマンドラインユーティリティを作成しています。これは製品コードであるため、大量のもの(エラーコード、スタックトレースなど)をダンプせずにクリーンにシャットダウンできるはずです。画面。これは、キーボードの割り込みをキャッチする必要があることを意味します。

私は両方のtry catchブロックを使用してみました:

if __== '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print 'Interrupted'
        sys.exit(0)

そして、シグナル自体をキャッチします( this post のように):

import signal
import sys

def sigint_handler(signal, frame):
    print 'Interrupted'
    sys.exit(0)
signal.signal(signal.SIGINT, sigint_handler)

どちらの方法も、通常の操作では非常にうまく機能するようです。ただし、アプリケーションの最後のクリーンアップコード中に割り込みが発生した場合、Pythonは常に何かを画面に出力するようです。割り込みをキャッチすると、

^CInterrupted
Exception KeyboardInterrupt in <bound method MyClass.__del__ of <path.to.MyClass object at 0x802852b90>> ignored

一方、信号の処理は、

^CInterrupted
Exception SystemExit: 0 in <Finalize object, dead> ignored

または

^CInterrupted
Exception SystemExit: 0 in <bound method MyClass.__del__ of <path.to.MyClass object at 0x802854a90>> ignored

これらのエラーは見苦しいだけでなく、あまり役に立ちません(特にソースコードのないエンドユーザーにとって)!

このアプリケーションのクリーンアップコードはかなり大きいため、この問題が実際のユーザーにヒットする可能性はかなりあります。この出力をキャッチまたはブロックする方法はありますか、それとも私が対処しなければならないものですか?

50
Dan

チェックアウト このスレッド 、終了とトレースバックに関する有用な情報があります。

プログラムを強制終了するだけに興味がある場合は、次のようなものを試してください(これにより、クリーンアップコードの下でも脚が削除されます)。

if __== '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print('Interrupted')
        try:
            sys.exit(0)
        except SystemExit:
            os._exit(0)
81
Dan Hogan

シャットダウンの開始後、クリーンアップコードを開始する前にsignal.signal(signal.SIGINT, signal.SIG_IGN)を呼び出すことにより、SIGINTを無視できます。

5
Dan Getz