PythonにKeyboardInterrupt
イベント内のすべてのコードをtry
-except
ステートメントに入れずにキャプチャする方法はありますか?
ユーザーが押すとトレースなしできれいに終了したい Ctrl+C。
はい、モジュール signal を使用して割り込みハンドラーをインストールし、 threading.Event を使用して永久に待機できます。
import signal
import sys
import time
import threading
def signal_handler(signal, frame):
print('You pressed Ctrl+C!')
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
print('Press Ctrl+C')
forever = threading.Event()
forever.wait()
トレースバックを表示したくない場合は、次のようにコードを作成します。
## all your app logic here
def main():
## whatever your app does.
if __== "__main__":
try:
main()
except KeyboardInterrupt:
# do nothing here
pass
はい
独自のシグナルハンドラを設定する代わりに、コンテキストマネージャを使用して例外をキャッチし、無視することもできます。
>>> class CleanExit(object):
... def __enter__(self):
... return self
... def __exit__(self, exc_type, exc_value, exc_tb):
... if exc_type is KeyboardInterrupt:
... return True
... return exc_type is None
...
>>> with CleanExit():
... input() #just to test it
...
>>>
これにより、try
-except
ブロックが削除されますが、何が起こっているのかについての明示的な言及は保持されます。
これにより、毎回シグナルハンドラを再度設定およびリセットすることなく、コードの一部でのみ割り込みを無視できます。
これは古い質問ですが、最初にここに来てatexit
モジュールを発見しました。クロスプラットフォームの実績や警告の完全なリストについてはまだ知りませんが、これまでのところ、Linuxでpost _KeyboardInterrupt
クリーンアップを処理しようとして探していたものです。別の方法で問題にアプローチしたかっただけです。
Fabric操作のコンテキストで終了後のクリーンアップを行いたいので、try
/except
ですべてをラップすることも私にとっては選択肢ではありませんでした。 atexit
は、コードが制御フローの最上位にないような状況に適していると思われます。
atexit
は、すぐに使用できる非常に優れた機能を備えています。次に例を示します。
import atexit
def goodbye():
print "You are now leaving the Python sector."
atexit.register(goodbye)
それをデコレータとして使用することもできます(2.6以降、この例はドキュメントからのものです):
import atexit
@atexit.register
def goodbye():
print "You are now leaving the Python sector."
KeyboardInterrupt
のみに限定したい場合は、この質問に対する他の人の答えがおそらく良いでしょう。
ただし、atexit
モジュールはコードの最大70行であり、例外をコールバック関数に引数として渡すなど、例外を異なる方法で処理する同様のバージョンを作成するのは難しくありません。 (変更されたバージョンを保証するatexit
の制限:現在、exit-callback-functionsが例外について知る方法を考えることができません。atexit
ハンドラーは例外をキャッチし、呼び出しますコールバック(複数可)、その例外を再レイズします。しかし、これを異なる方法で行うことができます。)
詳細については、以下を参照してください。
try: ... except KeyboardInterrupt: pass
を置き換えることで、sys.excepthook
なしでKeyboardInterrupt
のスタックトレースを印刷しないようにすることができます(最も明白で適切な「最良の」ソリューションですが、既に知っており、何か他のものを求めています)。何かのようなもの
def custom_excepthook(type, value, traceback):
if type is KeyboardInterrupt:
return # do nothing
else:
sys.__excepthook__(type, value, traceback)