ProcessPoolExecutor Python: обработка результатов и ошибок сериализации
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Concurrent futures Python: задачи на ThreadPoolExecutor и ProcessPoolExecutor.
Реестр исходов пула процессов
Испытательный стенд запускает пакет прикладных расчётов в ProcessPoolExecutor. Часть задач передаётся в виде обычных функций верхнего уровня модуля, но некоторые по ошибке оформлены как анонимные лямбды или вложенные функции. Модуль pickle не может разрешить имена таких объектов при передаче в дочерний процесс, что приводит к ошибкам сериализации.
Метод submit при вызове не падает синхронно: отказ проявляется только позже, когда стенд опрашивает полученные объекты Future. Поэтому системе нужно аккуратно сопоставить исходный идентификатор каждого расчёта с его фактическим исходом — полученным значением либо перехваченным исключением сериализации (PicklingError или AttributeError).
Реализуйте функцию запуска пакета, которая собирает реестр исходов с разделением на успешные расчёты и зафиксированные ошибки сериализации, строго сохраняя исходный порядок подачи задач.
Что уже дано
В среде выполнения уже объявлены готовые вспомогательные инструменты для тестирования пулов и сериализации:
make_process_probe(rows, workers=2)иmake_archive_probe(files, failures, workers=2);- метод
probe.run(), который запускает тестируемую функцию в рабочем пространстве имён; - вспомогательная функция сжатия
compress_block(file_id, data).
Вам предстоит реализовать функцию collect_process_outcomes.
Что нужно сделать
Реализуйте функцию collect_process_outcomes(jobs, pool).
Функция принимает два аргумента:
jobs— упорядоченный список кортежей вида(job_id, function, args)(от 0 до 8 элементов). Полеjob_id— уникальный непустой строковый идентификатор из символов ASCII длиной до 30 знаков.function— вызываемый объект (импортируемая функция модуля, лямбда или вложенная функция).args— кортеж позиционных аргументов для функции (числовые значения по модулю не превосходят 1 000 000, списки суммирования содержат до 32 элементов);pool— уже созданный экземплярProcessPoolExecutor.
Правила выполнения:
- Каждую функцию с её исходными аргументами необходимо отправить в переданный пул
poolчерез методpool.submit(function, *args)ровно один раз, сохранив связь междуjob_idи полученным объектомFuture. - Опросите каждый полученный
Futureна предмет результата или исключения. Ошибка сериализации одной задачи не должна приводить к сбросу или пропуску остальных задач. - Функция должна вернуть словарь ровно с двумя ключами:
"successes"и"errors". - Ключом словаря
"successes"являетсяjob_idуспешно выполненной задачи, а значением — фактически вычисленный результат. Порядок добавления записей должен строго соответствовать исходному порядку задач во входном спискеjobs. - Ключом словаря
"errors"являетсяjob_idзадачи, завершившейся ошибкой, а значением — точный исходный объект возникшего исключения (PicklingErrorилиAttributeError), сохранённый вFuture. Нельзя заменять объект ошибки строкой, типом или заново созданным исключением. - Если список
jobsпуст или в какую-либо категорию не попало ни одной задачи, соответствующий словарь должен быть пустым ({}).
Ввод и вывод
Стандартные потоки stdin и stdout не используются: считывать данные и выводить результат через print не требуется. Тестирующая система импортирует и вызывает функцию верхнего уровня collect_process_outcomes напрямую после выполнения кода решения.
Пример использования
probe = make_process_probe([{'id': 'good', 'kind': 'square', 'value': 6}, {'id': 'bad', 'kind': 'lambda', 'value': 3}])
observed = probe.run()
print(observed['successes'])
print([row['id'] for row in observed['errors']])
Вывод:
[('good', 36)]
['bad']
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- ProcessPoolExecutor и lambda: когда возникает ошибка pickle
- Concurrent.futures Python: первые K успешных результатов двух пулов
- Потоки и процессы Python: аварийная остановка двухэтапного конвейера
- ThreadPoolExecutor и ProcessPoolExecutor: загрузка и обработка данных
- Concurrent.futures Python: выбор исполнителя по размеру пакета
- Потоки и процессы Python: двухэтапное резервное копирование
