【发布时间】:2015-09-16 01:22:12
【问题描述】:
我正在尝试使用 Asyncio 和 aiohttp 库发出一堆请求(约 1000 个),但我遇到了一个我找不到太多信息的问题。
当我用 10 个 url 运行这段代码时,它运行得很好。当我使用 100 多个 url 运行它时,它会中断并给我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找到堆栈跟踪。
任何帮助或见解将不胜感激,因为我已经为此苦苦思索了几个小时。显然,这表明事件循环已关闭,但仍应打开,但我不明白这是怎么可能的。
【问题讨论】:
-
不是
Asyncio错误。 Python 递归错误,已达到限制。所有非类函数都需要线程... -
首先,确保您使用的是最新的 aiohttp 版本。我想你会的。从技术上讲,aiohttp 需要在完成关闭底层套接字的请求后进行一次循环迭代。所以在
loop.close()调用之前插入loop.run_until_complete(asyncio.sleep(0))。 -
您的回溯表明,提交到Executor 到run_in_executor 的作业在循环关闭后返回。奇怪的是,aiohttp 和 asyncio 不要使用
run_in_executor... -
@AndrewSvetlov,感谢您的回复 - 我尝试在收盘前睡觉,但仍然没有骰子......还有其他想法吗?
-
@Vincent 在技术上是这样做的,DNS 解析是由
run_in_executor执行的——但它应该在完成get_status任务之前完成。
标签: python python-3.x python-asyncio aiohttp