Неправильное использование requests в асинхронных корутинах

Корутины не содержат await и выполняют блокирующие requests-вызовы, поэтому фактически идут последовательно. Перенесите весь синхронный запрос в поток либо используйте общий async-клиент.

Короткий ответ

Что ответить на собеседовании

Корутины не содержат await и выполняют блокирующие requests-вызовы, поэтому фактически идут последовательно. Перенесите весь синхронный запрос в поток либо используйте общий async-клиент.

Подробный разбор

Ответ с пояснениями

Условие

В этом задании необходимо указать, какие ошибки возникают, когда пытаются собрать погодные данные для нескольких городов, комбинируя asyncio и синхронную библиотеку requests. Приведённый пример демонстрирует типичную ловушку: блокирующие HTTP‑запросы выполняются внутри async‑функции, из‑за чего цикл событий теряет преимущества параллельности. Опишите, почему такой код работает медленно, какие исключения могут появиться и как правильно организовать асинхронный доступ к API (например, используя aiohttp или исполняя запросы в пуле потоков).

import asyncio
import requests

async def fetch_weather(city_name):
    with requests.Session() as sess:
        endpoint = "http://api.openweathermap.org/data/2.5/weather"
        params = {'q': city_name, 'APPID': 'your_token_here'}
        with sess.get(url=endpoint, params=params) as resp:
            data = resp.json()
            print(f"{city_name}: {data['weather'][0]['main']}")

loop = asyncio.get_event_loop()
coros = [loop.create_task(fetch_weather(c)) for c in [
    'Moscow', 'St. Petersburg', 'Rostov-on-Don',
    'Kaliningrad', 'Vladivostok', 'Minsk', 'Beijing', 'Delhi'
]]
await_all = asyncio.wait(coros)

loop.run_until_complete(await_all)
loop.close()

Ответ

Корутины не содержат await и выполняют блокирующие requests-вызовы, поэтому фактически идут последовательно. Перенесите весь синхронный запрос в поток либо используйте общий async-клиент.

При использовании потоков вынесите HTTP-запрос, проверку статуса и разбор ответа в обычную функцию, затем вызывайте её через await asyncio.to_thread(...). Ограничьте число одновременных запросов семафором. Другой вариант — один aiohttp.ClientSession с timeout и ограниченным пулом соединений.

Используйте asyncio.run(main()) и gather, явно обрабатывая результаты и исключения задач. Исходный wait сам по себе не извлекает исключения завершённых задач. Возможны сетевые ошибки, некорректный JSON, отсутствие weather и пустой список. Не печатайте токен, не отправляйте его по HTTP; используйте HTTPS и настройку секретов вне кода.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее