python - Asyncio aiohttp 从 URL 列表中填充 HTML 列表
问题描述
我正在尝试从一个URL 异步获取一个list
HTML 源代码,但是我得到了 2 个异常:list
asyncio
aiohttp
TypeError('An asyncio.Future, a coroutine or an awaitable is ' TypeError: An asyncio.Future, a coroutine or an awaitable is required Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000001C92141F310>
raise RuntimeError('Event loop is closed') RuntimeError: Event loop is closed
这是我的代码:
import asyncio
import aiohttpasync
def main():
tasks = []
html_list = []
async with aiohttp.ClientSession() as session:
for url in ['http://www.apple.com', 'http://www.google.cl']:
async with session.get(url) as resp:
tasks.append(html_list.append(await resp.read()))
print(html_list[0])
print(html_list[1])
await(asyncio.wait(tasks))
if __name__ == '__main__':
asyncio.run(main())
这段代码会在我得到上述异常后立即打印html 代码。['http://www.apple.com', 'http://www.google.cl']
解决方案
您的示例有一些不太正确的地方:
你没有同时运行任何东西。当你
await resp.read()
在你的 for 循环中时,这会阻塞,main
直到结果返回。也许这就是您想要的,但您需要使用它asyncio.create_task
来同时运行您的请求。正如所指出的,由于
task
第一点,您根本不需要数组。你可以追加到html_list
.您不需要调用
asynio.wait
,因为此时您没有等待任何任务或协程。
您可以通过您在评论中所做的事情来解决您的直接问题,但同时运行的版本如下所示:
import asyncio
import aiohttp
async def read_url(session, url):
async with session.get(url) as resp:
return await resp.read()
async def main():
tasks = []
async with aiohttp.ClientSession() as session:
for url in ['http://www.apple.com', 'http://www.google.cl']:
tasks.append(asyncio.create_task(read_url(session, url)))
html_list = await asyncio.gather(*tasks)
print(html_list[0])
print(html_list[1])
if __name__ == '__main__':
asyncio.run(main())
在这里,我们定义了一个协程read_url
,它获取单个 url 的内容。然后在循环中,您创建一个用于读取 url 的任务并将其附加到tasks
列表中。然后你使用asyncio.gather
- 这将等待所有任务同时完成。
如所写,我无法重现您的RuntimeError: Event loop is closed
错误。