如何停止具有多个任务的异步循环

eSl*_*vko 3 python python-asyncio

我不知道如何在一项任务完成后停止循环。在示例中,当 WsServe 计数到 5 时,我预计循环会关闭。但相反,我得到了RuntimeError: Cannot close a running event loop

#!/usr/bin/env python
import asyncio

async def rxer():
    i=0
    while True:
        i+=1
        print ('Rxer ',i)
        await asyncio.sleep(1)

async def WsServe():
    for i in range(5):
        print ('WsServe',i)
        await asyncio.sleep(1)

    print ('Finish')
    loop.stop()
    loop.close()

loop=asyncio.get_event_loop()
loop.create_task(rxer())
loop.run_until_complete(WsServe())
loop.run_forever()
Run Code Online (Sandbox Code Playgroud)

use*_*342 5

该错误来自loop.close()循环内部的调用。您不需要费心loop.close()loop.stop()就足以停止循环。loop.close()仅当您想要确保释放循环内部获取的所有资源时才相关。当您的进程即将退出时,不需要它,并且删除对的调用确实可以loop.close()消除错误。

而且,loop.stop()与 不兼容run_until_complete()。它恰好在这段代码中起作用,因为协程在调用后立即返回loop.stop();如果你添加了一个await asyncio.sleep(1)after loop.stop(),你会再次得到一个(不同的)RuntimeError

为了避免此类问题,我建议您迁移到较新的asyncio.runAPI 并避免同时使用run_until_completestop。相反,您可以仅使用事件来终止 main 函数及其循环:

# rxer() defined as before

async def WsServe(stop_event):
    for i in range(5):
        print ('WsServe',i)
        await asyncio.sleep(1)

    print ('Finish')
    stop_event.set()
    await asyncio.sleep(1)

async def main():
    asyncio.get_event_loop().create_task(rxer())
    stop_event = asyncio.Event()
    asyncio.get_event_loop().create_task(WsServe(stop_event))
    await stop_event.wait()

asyncio.run(main())

# python 3.6 and older:
#asyncio.get_event_loop().run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)