Извлечение нескольких URL-адресов с помощью aiohttp в Python 3.5

Начиная с версии Python 3.5 async with синтаксис, рекомендуемый в документах для aiohttp изменился Теперь, чтобы получить один URL, они предлагают:

import aiohttp
import asyncio

async def fetch(session, url):
    with aiohttp.Timeout(10):
        async with session.get(url) as response:
            return await response.text()

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    with aiohttp.ClientSession(loop=loop) as session:
        html = loop.run_until_complete(
            fetch(session, 'http://python.org'))
        print(html)

Как я могу изменить это, чтобы получить коллекцию URL вместо одного URL?

В старом asyncio примеры вы бы настроить список задач, таких как

    tasks = [
            fetch(session, 'http://cnn.com'),
            fetch(session, 'http://google.com'),
            fetch(session, 'http://twitter.com')
            ]

Я попытался объединить этот список с подходом, описанным выше, но не получилось.

1 ответ

Решение

Для параллельного выполнения вам нужен asyncio.Task

Я преобразовал ваш пример в одновременную выборку данных из нескольких источников:

import aiohttp
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        if response.status != 200:
            response.raise_for_status()
        return await response.text()

async def fetch_all(session, urls):
    results = await asyncio.gather(*[asyncio.create_task(fetch(session, url))
                                   for url in urls])
    return results

async def main():    
    urls = ['http://cnn.com',
            'http://google.com',
            'http://twitter.com']
    async with aiohttp.ClientSession() as session:
        htmls = await fetch_all(session, urls)
        print(htmls)

if __name__ == '__main__':
    asyncio.run(main())
Другие вопросы по тегам