Asyncio RuntimeError:事件循环已关闭

时间:2015-09-16 01:22:12

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

我正在尝试使用Asyncio和aiohttp库发出一堆请求(~1000),但我遇到了一个我找不到太多信息的问题。

当我用10个网址运行此代码时,它运行得很好。当我用100多个网址运行它时,它会中断并给我RuntimeError: Event loop is closed错误。

import asyncio
import aiohttp


@asyncio.coroutine
def get_status(url):
    code = '000'
    try:
        res = yield from asyncio.wait_for(aiohttp.request('GET', url), 4)
        code = res.status
        res.close()
    except Exception as e:
        print(e)
    print(code)


if __name__ == "__main__":
    urls = ['https://google.com/'] * 100
    coros = [asyncio.Task(get_status(url)) for url in urls]
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(coros))
    loop.close()

可以找到堆栈跟踪here

任何帮助或见解都会受到高度赞赏,因为我现在已经在这几个小时内对此表示不满。显然,这表明事件循环已经关闭,应该仍然是开放的,但我不知道这是怎么可能的。

2 个答案:

答案 0 :(得分:18)

该错误归档为https://github.com/python/asyncio/issues/258 请继续关注。

作为快速解决方法,我建议使用自定义执行程序,例如

loop = asyncio.get_event_loop()
executor = concurrent.futures.ThreadPoolExecutor(5)
loop.set_default_executor(executor)

在完成您的计划之前,请执行

executor.shutdown(wait=True)
loop.close()

答案 1 :(得分:5)

你是对的,this使用Windows.UI.Xaml.Printing.PrintDocument在一个帖子中运行ThreadPoolExecutor

您正在使用loop.getaddrinfo超时,这意味着socket.getaddrinfo将在4秒后引发res = yield from asyncio.wait_for...。然后asyncio.TimeoutError协同程序返回get_status并且循环停止。如果作业在此之后完成,它将尝试在事件循环中安排回调并引发异常,因为它已经关闭。