我正在尝试使用asyncio
编写并发Python程序,该程序也接受键盘输入。当我尝试关闭程序时出现问题。由于键盘输入最后都是用sys.stdin.readline
完成的,因此该函数仅在我按ENTER
之后返回,无论我是stop()
事件循环还是cancel()
函数的{{1 }}。
有什么方法可以提供可以取消的Future
键盘输入?
这是我的MWE。它将接受键盘输入1秒钟,然后接受asyncio
:
stop()
答案 0 :(得分:1)
问题在于执行者坚持要确保在程序终止时所有正在运行的期货都已完成。但是在这种情况下,您实际上想要一个“不干净”的终止,因为没有可移植的方式来取消正在进行的read()
或异步访问sys.stdin
。
取消未来没有任何作用,因为一旦concurrent.futures.Future.cancel
的回调开始执行后,它便是无操作的。避免不必要的等待的最佳方法是首先避免run_in_executor
,而只产生自己的线程:
async def ainput():
loop = asyncio.get_event_loop()
fut = loop.create_future()
def _run():
line = sys.stdin.readline()
loop.call_soon_threadsafe(fut.set_result, line)
threading.Thread(target=_run, daemon=True).start()
return await fut
该线程是手动创建的,并标记为“守护程序”,因此没有人会在程序关闭时等待它。结果,使用ainput
而不是run_in_executor(sys.stdin.readline)
的代码变体将按预期终止:
async def console_input_loop():
while True:
inp = await ainput()
print(f"[{inp.strip()}]")
# rest of the program unchanged