如何在执行程序任务仍在等待控制台输入的情况下干净地退出 python 异步应用程序
How to cleanly exit a python async app with executor tasks still waiting for console input
我正在尝试将控制台输入侦听器添加到异步应用程序,但我遇到了一个有趣的问题。
以下代码没有在应该终止的时候终止,而是在脚本终止后继续等待输入:
import asyncio
loop = asyncio.get_event_loop()
async def quit_after(timeout):
await asyncio.sleep(timeout)
print('main function terminating now') # this could simulate a crash, or a proper exit
async def print_input_loop():
while True:
# executor thread is daemon - should terminate when script ends, but doesn't
text = await loop.run_in_executor(None, input, '> ')
print(text)
if __name__ == '__main__':
loop.create_task(print_input_loop())
try:
loop.run_until_complete(quit_after(5))
finally:
loop.close()
print('reached end of file - script should now terminate')
我研究了其他异步获取输入的方法,例如使用 add_reader() on sys.stdin,但这在 Windows 上不起作用,我需要我的解决方案独立于平台。
有没有人知道更好的异步获取控制台输入的方法,当应用程序停止时将正常停止,或者修复我现有代码以使其干净退出的方法?
一个可能的解决方法是禁用 exit function for threads in concurrent.futures:
def disable_exit_for_threadpool_executor():
import atexit
import concurrent.futures
atexit.unregister(concurrent.futures.thread._python_exit)
此外,aioconsole 提供了一个 cross-platform 函数来处理 asyncio 中的控制台输入:
import aioconsole
async def echo_loop():
while True:
text = await aioconsole.ainput('> ')
print(text.strip())
尽管 确实解决了您的问题,但我还是建议您在构建 asyncio
程序时尽量不要使用 input()
。
相反,使用套接字(或信号)为协程提供输入。
即,而不是:
$ ./myprogram.py
> command
> command
> command
做:
$ ./myprogram.py
myprogram listens on port 9876
$ # from a different terminal:
$ telnet localhost 9876
Connected!
> command
> command
> command
我正在尝试将控制台输入侦听器添加到异步应用程序,但我遇到了一个有趣的问题。
以下代码没有在应该终止的时候终止,而是在脚本终止后继续等待输入:
import asyncio
loop = asyncio.get_event_loop()
async def quit_after(timeout):
await asyncio.sleep(timeout)
print('main function terminating now') # this could simulate a crash, or a proper exit
async def print_input_loop():
while True:
# executor thread is daemon - should terminate when script ends, but doesn't
text = await loop.run_in_executor(None, input, '> ')
print(text)
if __name__ == '__main__':
loop.create_task(print_input_loop())
try:
loop.run_until_complete(quit_after(5))
finally:
loop.close()
print('reached end of file - script should now terminate')
我研究了其他异步获取输入的方法,例如使用 add_reader() on sys.stdin,但这在 Windows 上不起作用,我需要我的解决方案独立于平台。
有没有人知道更好的异步获取控制台输入的方法,当应用程序停止时将正常停止,或者修复我现有代码以使其干净退出的方法?
一个可能的解决方法是禁用 exit function for threads in concurrent.futures:
def disable_exit_for_threadpool_executor():
import atexit
import concurrent.futures
atexit.unregister(concurrent.futures.thread._python_exit)
此外,aioconsole 提供了一个 cross-platform 函数来处理 asyncio 中的控制台输入:
import aioconsole
async def echo_loop():
while True:
text = await aioconsole.ainput('> ')
print(text.strip())
尽管 asyncio
程序时尽量不要使用 input()
。
相反,使用套接字(或信号)为协程提供输入。
即,而不是:
$ ./myprogram.py
> command
> command
> command
做:
$ ./myprogram.py
myprogram listens on port 9876
$ # from a different terminal:
$ telnet localhost 9876
Connected!
> command
> command
> command