15

在 Windows 上使用 Python 3.4.1,我发现在执行asyncio 事件循环时,我的程序不能被中断(即在终端中按 Ctrl+C)。更重要的是,SIGINT 信号被忽略。相反,我已经确定 SIGINT 在不在事件循环中时被处理。

为什么在执行异步事件循环时忽略 SIGINT?

下面的程序应该演示这个问题 - 在终端中运行它并尝试通过按 Ctrl+C 来停止它,它应该继续运行:

import asyncio
import signal


# Never gets called after entering event loop
def handler(*args):
    print('Signaled')


signal.signal(signal.SIGINT, handler)

print('Event loop starting')
loop = asyncio.SelectorEventLoop()
asyncio.set_event_loop(loop)
loop.run_forever()
print('Event loop ended')

请参阅官方(郁金香)邮件列表上的讨论。

4

3 回答 3

14

I've found a workaround, which is to schedule a periodic callback. While this running, SIGINT is apparently processed:

import asyncio


def wakeup():
    # Call again
    loop.call_later(0.1, wakeup)


print('Event loop starting')
loop = asyncio.SelectorEventLoop()
# Register periodic callback
loop.call_later(0.1, wakeup)
asyncio.set_event_loop(loop)
loop.run_forever()
print('Event loop ended')

Not sure why this is necessary, but it indicates that signals are blocked while the event loop waits for events ("polls").

The matter has been discussed on the official (Tulip) mailing list, my workaround is apparently the way to go as of now.

Update

A fix has supposedly made its way into Python 3.5, so hopefully my workaround will be made obsolete by that Python version.

于 2014-07-16T07:50:04.360 回答
6

我发现在执行异步事件循环时,我的程序不能被中断(即通过在终端中按 Ctrl+C)

澄清一下: ctrl-C 可能不起作用,但 ctrl-break 工作得很好。

于 2014-10-29T03:20:19.577 回答
2

通常,您会为这些添加回调,loop.add_signal_handler()但显然不幸的是,内置 Windows 事件循环不支持此功能:/

可以使用定期检查,是的。否则,循环将超出signal模块捕获信号的能力。

于 2014-07-16T07:53:32.547 回答