回答:
はい、モジュールシグナルを使用して割り込みハンドラーをインストールし、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()
while True: continue
、絶対にやらないでほしい。(そのスタイルでwhile True: pass
は、とにかくすっきりします。)それは非常に無駄です。のようなものを試してくださいwhile True: time.sleep(60 * 60 * 24)
(一度に1日寝ることは完全に恣意的な数字です)。
time
(必要に応じて)Chris Morganの使用の提案を使用している場合は、忘れずにimport time
:)
トレースバックを表示したくない場合は、次のようにコードを作成します。
## 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の煩わしさが軽減される可能性があります)
signal.signal( signal.SIGINT, lambda s, f : sys.exit(0))
常にそうします。
独自のシグナルハンドラーを設定する代わりに、コンテキストマネージャーを使用して例外をキャッチし、無視します。
>>> 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でポストクリーンアップを処理するために探していたものとまったく同じです。問題に取り組む別の方法で投げたかっただけです。
私は、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
ハンドラが例外をキャッチし、コールバックを呼び出してから、再度レイズしますその例外です。ただし、これは別の方法で行うことができます。)
詳細については、以下を参照してください。
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