Asyncio TaskGroup: сбор результатов с отменёнными задачами
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Asyncio TaskGroup и gather: задачи на ошибки и отмену корутин.
Сбор результатов валидации документов
Сервис распределённой проверки документов запускает группу независимых валидаторов внутри контекста asyncio.TaskGroup. Во время работы отдельный валидатор может решить, что документ проверять не нужно, и самостоятельно завершиться возбуждением asyncio.CancelledError. По контракту группы такая точечная отмена не считается сбоем и не приводит к каскадной отмене остальных проверок.
Сложность возникает уже после выхода из контекста, когда диспетчер начинает подводить итоги. Прямой вызов task.result() у отменённой задачи повторно выбрасывает CancelledError, из-за чего весь процесс сбора результатов может аварийно завершиться.
Диспетчеру необходимо аккуратно обойти все задачи группы и проверить индивидуальный статус каждой из них. Успешные результаты требуется сохранить в итоговый словарь, а отменённые проверки отметить специальным маркером пропуска, не допуская необработанного исключения.
Что уже дано
В среде выполнения доступен модуль asyncio и специальный уникальный объект-маркер SKIPPED. В редакторе представлена заготовка асинхронной функции collect_validators(validators).
Что нужно сделать
Реализуйте асинхронную функцию collect_validators(validators) -> dict[str, object].
Параметр validators — словарь, содержащий от 0 до 50 элементов. Ключами являются уникальные строковые имена длиной от 1 до 64 символов, а значениями — фабрики без аргументов, возвращающие корутины проверки.
Требования к выполнению:
- Запустите корутину каждого валидатора ровно один раз строго внутри контекстного менеджера
asyncio.TaskGroup. - Все созданные задачи должны быть полностью завершены до выхода из функции. Оставлять незавершённые фоновые задачи в цикле событий запрещено.
- Каждый валидатор либо завершается успешно, возвращая значение (скаляр, список, словарь, включая
None,False,0и пустые структуры данных), либо выполняет самоотмену возбуждениемasyncio.CancelledError. Обычные исключения валидаторы не выбрасывают. - Самоотмена отдельного валидатора не должна приводить к отмене остальных проверок.
- После завершения работы группы сформируйте и верните словарь, ключи которого в точности совпадают с ключами входного словаря
validators(порядок ключей значения не имеет): - для завершившегося штатно валидатора значением должно быть возвращённое им значение (включая
None,False,0и пустые коллекции); - для отменённого валидатора значением должен стать точный предоставленный маркер
SKIPPED(не строка'SKIPPED'и неNone). - Чтение результата отменённой задачи не должно приводить к падению функции из-за необработанного
asyncio.CancelledError. - Если на вход передан пустой словарь
validators, функция должна вернуть пустой словарь{}.
Ввод и вывод
Стандартные потоки stdin и stdout не используются: считывать данные и выводить результат через print не требуется. Тестирующая система после выполнения скрипта получает функцию верхнего уровня collect_validators, передаёт в неё словарь с именами и фабриками корутин и ожидает её завершения.
Пример использования
async def valid():
await asyncio.sleep(0)
return None
async def skipped():
raise asyncio.CancelledError()
async def example():
answers = await collect_validators({"A": valid, "B": skipped})
print(answers["A"] is None)
print(answers["B"] is SKIPPED)
asyncio.run(example())
Вывод:
True True
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- Asyncio TaskGroup и gather: что происходит при ошибке корутины
- Asyncio gather: отмена оставшихся задач при ошибке
- Asyncio TaskGroup: обработка ошибок параллельного опроса
- Asyncio TaskGroup: двухфазная проверка и публикация конфигурации
- Asyncio gather и TaskGroup: соберите исключения конкурентных задач
- Удаление ключа из ChainMap в Python: проверка поведения del
