すべてのコードを--ステートメントKeyboardInterrupt
内に配置せずにイベントをキャプチャする方法はPythonにありますか?try
except
Ctrlユーザーが+を押した場合、トレースなしでクリーンに終了したいC。
すべてのコードを--ステートメントKeyboardInterrupt
内に配置せずにイベントをキャプチャする方法はPythonにありますか?try
except
Ctrlユーザーが+を押した場合、トレースなしでクリーンに終了したいC。
はい、モジュールシグナルを使用して割り込みハンドラーをインストールし、 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 __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
# do nothing here
pass
(はい、これが質問に直接答えないことは知っていますが、try /exceptブロックが必要なことが好ましくない理由は明確ではありません-おそらくこれによりOPの煩わしさが軽減されます)
独自のシグナルハンドラを設定する代わりに、コンテキストマネージャを使用して例外をキャッチし、無視することもできます。
>>> 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
モジュールを発見しました。クロスプラットフォームの実績や警告の完全なリストについてはまだわかりませんが、これまでのところ、KeyboardInterrupt
Linuxでのクリーンアップ後の処理を試みる際に探していたものです。問題にアプローチする別の方法を投入したかっただけです。
ファブリック操作のコンテキストで終了後のクリーンアップを実行したいので、すべてを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
ハンドラーは例外をキャッチし、コールバックを呼び出してから、再レイズします。その例外。しかし、これは別の方法で行うことができます。)
詳細については、以下を参照してください。
atexit
を置き換えることで、(最も明白でおそらく「最良の」解決策ですが、すでにそれを知っていて、何か他のものを求めている)KeyboardInterrupt
なしで、のスタックトレースを印刷することを防ぐことができます。何かのようなものtry: ... except KeyboardInterrupt: pass
sys.excepthook
def custom_excepthook(type, value, traceback):
if type is KeyboardInterrupt:
return # do nothing
else:
sys.__excepthook__(type, value, traceback)
提案された解決策をみんなで試しましたが、実際に機能させるには、自分でコードを即興で作成する必要がありました。以下は私の即興のコードです:
import signal
import sys
import time
def signal_handler(signal, frame):
print('You pressed Ctrl+C!')
print(signal) # Value is 2 for CTRL + C
print(frame) # Where your execution of program is at moment - the Line Number
sys.exit(0)
#Assign Handler Function
signal.signal(signal.SIGINT, signal_handler)
# Simple Time Loop of 5 Seconds
secondsCount = 5
print('Press Ctrl+C in next '+str(secondsCount))
timeLoopRun = True
while timeLoopRun:
time.sleep(1)
if secondsCount < 1:
timeLoopRun = False
print('Closing in '+ str(secondsCount)+ ' seconds')
secondsCount = secondsCount - 1