Как соединить асинхронно полученные данные сайта, сохранив порядок и структуру
Что проверяют
Понимаете ли вы, что асинхронные ответы приходят в произвольном порядке, и знаете ли, как вернуть исходный. Следом почти всегда спрашивают про ограничение параллельности и ошибки: что будет, если из сотни запросов упадут три.
Как отвечать
Основной инструмент это asyncio.gather: он возвращает результаты в порядке переданных корутин, а не в порядке завершения.
async with aiohttp.ClientSession() as session:
results = await asyncio.gather(*(fetch(session, u) for u in urls), return_exceptions=True)Дальше покажите, что знаете детали:
- ошибки: по умолчанию
gatherпробрасывает первое исключение, а остальные задачи продолжают работать. Сreturn_exceptions=Trueисключения лежат в списке на своих местах, их легко отфильтровать; TaskGroup: с Python 3.11 структурная альтернатива. При ошибке одной задачи остальные отменяются, результаты берёте черезtask.result()в порядке создания;as_completed: отдаёт результаты по мере готовности, порядок теряется. Если нужен прогресс, возвращайте индекс или ключ вместе с данными и раскладывайте в словарь или заранее созданный список по позиции;- параллельность:
asyncio.SemaphoreилиlimitуTCPConnectorвaiohttp, иначе сотня одновременных запросов упрётся в лимиты сайта или бан; - структура: если данные иерархические, например страница списка и карточки товаров, храните связь явно, ключ родителя в каждом результате, а сборку делайте после получения всех частей.
Для потоков то же даёт ThreadPoolExecutor.map: результаты тоже идут в порядке входа.
Где спотыкаются
Добавляют результаты в общий список через append внутри корутины. Порядок получается случайным, и кандидат не может объяснить, почему тест проходит через раз.
Не ограничивают число одновременных запросов. На собеседовании это выглядит как незнание того, как сайты ведут себя под нагрузкой.
Считают, что gather при первой ошибке отменяет остальные задачи. Это не так: они выполняются дальше, а их результаты теряются, если не взять return_exceptions=True или TaskGroup.