web-dev-qa-db-ja.com

asyncioのイベントループがWindowsでKeyboardInterruptを抑制するのはなぜですか?

asyncioイベントループを実行する以外に何もしないこの本当に小さなテストプログラムがあります。

_import asyncio
asyncio.get_event_loop().run_forever()
_

Linuxでこのプログラムを実行してを押すと Ctrl+C、プログラムはKeyboardInterrupt例外で正しく終了します。 Windowsの場合 Ctrl+C 何もしません(Python 3.4.2でテスト済み)。time.sleep()を使用した単純な無限ループは、WindowsでもKeyboardInterruptを正しく発生させます。

_import time
while True:
    time.sleep(3600)
_

AsyncioのイベントループがWindowsでKeyboardInterruptを抑制するのはなぜですか?

28
skrause

これは確かにバグです。

問題解決の進捗状況については、 issue on python bug-tracker を参照してください。

17
Andrew Svetlov

Windowsには回避策があります。毎秒ループをウェイクアップし、ループがキーボード割り込みに反応できるようにする別のコルーチンを実行します

AsynciodocのEchoサーバーの例

async def wakeup():
    while True:
        await asyncio.sleep(1)

loop = asyncio.get_event_loop()
coro = loop.create_server(EchoServerClientProtocol, '127.0.0.1', 8888)
server = loop.run_until_complete(coro)

# add wakeup HACK
loop.create_task(wakeup())

try:
    loop.run_forever()
except KeyboardInterrupt:
    pass
13
farincz

プログラムを終了したいだけでKeyboardInterruptをキャッチする必要がない場合、 signal モジュールはより単純な(そしてより効率的な)回避策を提供します。

# This restores the default Ctrl+C signal handler, which just kills the process
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)

# Now the event loop is interruptable
import asyncio
asyncio.get_event_loop().run_forever()
9
Bart Robinson