首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python异步程序不会退出等待stdin输入。

Python异步程序不会退出等待stdin输入。
EN

Stack Overflow用户
提问于 2022-04-20 23:44:57
回答 1查看 115关注 0票数 1

我有一个复杂的Python3.9程序,如果被Ctrl (SIGINT)中断,它不会退出。下面是这个问题的最小再现。使用python sample.py运行时,您应该会看到两个输入提示,然后是一个正常的退出。如果在第一个提示符上按下Ctrl,它就会像预期的那样退出。如果在第二个提示符下按下Ctrl,什么都不会发生,直到您按下Enter (然后在selectors.py的深处发生一个不知名的selectors.py)。

代码语言:javascript
复制
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?我怎么才能解决这个问题?

输出

代码语言:javascript
复制
$ 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
EN

回答 1

Stack Overflow用户

发布于 2022-04-29 23:35:06

所发生的是KeyboardInterruptasyncio捕获,因为您正在使用threading。然后,asyncio通过尝试取消它来将其输入协同线,这会引发asyncio.CancelledError。你可以这样处理:

代码语言:javascript
复制
async def main():
    try:
        input("1>")
        await ainput("2>")
    except KeyboardInterrupt:
        print("Ctrl-C")
    except asyncio.CancelledError:
        print("Cancelled?")
        raise

但是,没有任何方法阻止asyncio.run(...)提高KeyboardInterrupt,至少AFAIK是这样的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71947315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档