我有一个复杂的Python3.9程序,如果被Ctrl (SIGINT)中断,它不会退出。下面是这个问题的最小再现。使用python sample.py运行时,您应该会看到两个输入提示,然后是一个正常的退出。如果在第一个提示符上按下Ctrl,它就会像预期的那样退出。如果在第二个提示符下按下Ctrl,什么都不会发生,直到您按下Enter (然后在selectors.py的深处发生一个不知名的selectors.py)。
import asyncio
async def ainput(prompt: str = "") -> str:
return await asyncio.get_event_loop().run_in_executor(None, input, prompt)
async def main():
try:
input("1>") # ctrl-C here works as expected, prints the message and exits
await ainput("2>") # ctrl-C here does nothing until you hit Enter
except KeyboardInterrupt:
print("Ctrl-C")
asyncio.run(main())问题
这是上面代码中的错误吗?还是异步中的一个bug?我怎么才能解决这个问题?
输出
$ python sample.py
1>asks
2>lsls
$ python sample.py
1>^CCtrl-C
$ python sample.py
1>slsl
2>^C # **nothing happens here until you hit Enter**
Traceback (most recent call last):
File "/Users/me/work/experimental/sample.py", line 15, in <module>
asyncio.run(main())
File "/opt/homebrew/Caskroom/miniforge/base/envs/alexa/lib/python3.9/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/opt/homebrew/Caskroom/miniforge/base/envs/alexa/lib/python3.9/asyncio/base_events.py", line 634, in run_until_complete
self.run_forever()
File "/opt/homebrew/Caskroom/miniforge/base/envs/alexa/lib/python3.9/asyncio/base_events.py", line 601, in run_forever
self._run_once()
File "/opt/homebrew/Caskroom/miniforge/base/envs/alexa/lib/python3.9/asyncio/base_events.py", line 1869, in _run_once
event_list = self._selector.select(timeout)
File "/opt/homebrew/Caskroom/miniforge/base/envs/alexa/lib/python3.9/selectors.py", line 562, in select
kev_list = self._selector.control(None, max_ev, timeout)
KeyboardInterrupt发布于 2022-04-29 23:35:06
所发生的是KeyboardInterrupt被asyncio捕获,因为您正在使用threading。然后,asyncio通过尝试取消它来将其输入协同线,这会引发asyncio.CancelledError。你可以这样处理:
async def main():
try:
input("1>")
await ainput("2>")
except KeyboardInterrupt:
print("Ctrl-C")
except asyncio.CancelledError:
print("Cancelled?")
raise但是,没有任何方法阻止asyncio.run(...)提高KeyboardInterrupt,至少AFAIK是这样的。
https://stackoverflow.com/questions/71947315
复制相似问题