7

次のプログラムは、を無視するように端末をハングアップしCtrl+Cます。スレッドの1つがハングするたびにターミナルを再起動する必要があるため、これはかなり面倒です。

KeyboardInterruptイベントを待っている間にキャッチする方法はありますか?

import threading
def main():
    finished_event = threading.Event()
    startThread(finished_event)
    finished_event.wait()#I want to stop the program here
    print('done!')
def startThread(evt):
    """Start a thread that will trigger evt when it is done"""
    #evt.set()
if __name__ == '__main__':
    main()
4

4 に答える 4

5

ポーリングを避けたい場合は、の代わりにシグナルモジュールのpause()機能を使用できます。はブロッキング機能であり、プロセスがシグナルを受信するとブロックが解除されます。この場合、^ Cを押すと、SIGINTシグナルが関数のブロックを解除します。ドキュメントによると、この関数はWindowsでは機能しないことに注意してください。Linuxで試してみましたが、うまくいきました。finished_event.wait()signal.pause()

私はこのSOスレッドでこのソリューションに出くわしました。

于 2015-06-14T16:24:23.607 に答える
4

更新:現在のPython 3finished_event.wait()では、Ubuntuマシンで動作します(Python 3.2以降)。timeoutを使用してパラメータを中断するために、パラメータを指定する必要はありませんCtrl+CtimeoutCPython2でパラメーターを渡す必要があります。

完全なコード例は次のとおりです。

#!/usr/bin/env python3
import threading

def f(event):
    while True:
        pass
    # never reached, otherwise event.set() would be here

event = threading.Event()
threading.Thread(target=f, args=[event], daemon=True).start()
try:
    print('Press Ctrl+C to exit')
    event.wait()
except KeyboardInterrupt:
    print('got Ctrl+C')

Ctrl+Cに関連するバグがある可能性があります。ご使用の環境で機能するかどうかをテストします。


古いポーリングの答え:

インタプリタがメインスレッドを実行できるようにすることができます。

while not finished_event.wait(.1): # timeout in seconds
    pass

子スレッドが完了するまで待ちたい場合:

while thread.is_alive():
    thread.join(.1)
于 2013-01-20T03:02:31.143 に答える
1

次の方法でEvent.wait()関数にパッチを適用することもできます。

def InterruptableEvent():
    e = threading.Event()

    def patched_wait():
        while not e.is_set():
            e._wait(3)

    e._wait = e.wait
    e.wait = patched_wait
    return e


>>> event = InterruptableEvent()
>>> try:
...     event.wait()
... except KeyboardInterrupt:
...     print "Received KeyboardInterrupt"
... 
^CReceived KeyboardInterrupt

これが機能するのは、timeout引数を指定したwait()によってKeyboardInterruptが発生するためです。

于 2015-10-03T10:38:11.093 に答える
1

@Peteの回答に基づいていますが、サブクラス化して実際のEvent.waitメソッドを使用し、タイムアウトを小さくしてKeyboardInterrupt、その間のsなどを処理できるようにします。

class InterruptableEvent(threading.Event):
    def wait(self, timeout=None):
        wait = super().wait  # get once, use often
        if timeout is None:            
            while not wait(0.01):  pass
        else:
            wait(timeout)
于 2020-03-18T12:36:54.267 に答える