如何干净地退出python异步应用程序与执行程序任务仍在等待控制台输入

时间:2017-02-17 02:26:24

标签: python python-3.x python-asyncio

我正在尝试将控制台输入监听器添加到异步应用程序中,我遇到了一个有趣的问题。

以下代码在应该终止时不会终止,而是在脚本终止后继续等待输入:

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()上使用sys.stdin,但这在Windows上不起作用,我需要我的解决方案与平台无关。 / p>

有没有人知道一种更好的方法来异步获取控制台输入,以便在应用程序停止时正常停止,或者是一种修复现有代码以便干净地退出的方法?

2 个答案:

答案 0 :(得分:3)

可能的解决方法是为exit function中的线程禁用concurrent.futures

def disable_exit_for_threadpool_executor():
    import atexit
    import concurrent.futures
    atexit.unregister(concurrent.futures.thread._python_exit)

此外,aioconsole提供了一个跨平台功能,用于处理asyncio中的控制台输入:

import aioconsole

async def echo_loop():
    while True:
        text = await aioconsole.ainput('> ')
        print(text.strip())

答案 1 :(得分:0)

虽然Vincent's answer above确实解决了您的问题,但我建议您在构建input()计划时尽量不要使用asyncio

相反,使用套接字(或信号)为协同程序提供输入。

即,而不是:

$ ./myprogram.py
> command
> command
> command

执行:

$ ./myprogram.py
myprogram listens on port 9876

$ # from a different terminal:
$ telnet localhost 9876
Connected!
> command
> command
> command