Asyncio aiohttp заполнить список HTML из списка URL-адресов - PullRequest
0 голосов
/ 01 августа 2020

Я пытаюсь получить list из HTML исходного кода из list URL-адресов асинхронно с asyncio и aiohttp, но получаю 2 исключения:

  1. 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>
  2. 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'], но сразу после того, как я получу вышеупомянутые исключения.

1 Ответ

1 голос
/ 02 августа 2020

Есть несколько вещей, которые не совсем подходят вашему примеру:

  1. Вы ничего не запускаете одновременно. Когда вы await resp.read() в своем for l oop, это блокирует main, пока не вернется результат. Возможно, это то, что вы хотите, но вам нужно использовать asyncio.create_task для одновременного выполнения ваших запросов.

  2. Как уже отмечалось, вам вообще не нужен массив task, потому что пункта номер один. Вы можете просто добавить к html_list.

  3. Вам не нужно звонить 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. Затем в l oop вы создаете задачу для чтения URL-адреса и добавляете ее в список tasks. Затем вы используете asyncio.gather - это будет ждать, пока все задачи завершатся sh одновременно.

Как написано, я не могу воспроизвести вашу RuntimeError: Event loop is closed ошибку.

...