Потоки и процессы Python: двухэтапное резервное копирование
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Concurrent futures Python: задачи на ThreadPoolExecutor и ProcessPoolExecutor.
Двухэтапное резервное копирование
Модуль фонового резервного копирования обрабатывает входящие файлы в два этапа. Сначала он вычитывает сырые блоки данных из сетевого хранилища, а затем сжимает полученный массив тяжелым алгоритмом с расчетом контрольной суммы. Поскольку сетевая загрузка почти не нагружает процессор, её выполняют в пуле потоков ThreadPoolExecutor. Процедура сжатия, напротив, полностью загружает ядро вычислениями и направляется в пул процессов ProcessPoolExecutor.
Если сетевое чтение конкретного файла завершается ошибкой, задача сжатия для него вовсе не создается. В итоговом реестре такой файл помечается как пропущенный с сохранением текста возникшей сетевой ошибки.
Спроектируйте диспетчер двухэтапной обработки, который возвращает словарь с успешными контрольными суммами и зафиксированными сетевыми сбоями с сохранением исходного порядка файлов.
Что уже дано
При выполнении программы уже доступны готовые тестовые средства make_archive_probe, make_process_probe, а также функция сжатия compress_block(file_id, data). Реализовывать заново алгоритмы сетевого чтения и сжатия не требуется: они передаются аргументами в вашу функцию.
Вам необходимо написать реализацию функции archive_files.
Что нужно сделать
Реализуйте функцию archive_files(file_ids, fetch, compress, io_pool, cpu_pool).
Параметры функции:
file_ids— упорядоченный список, содержащий от 0 до 8 уникальных непустых ASCII-идентификаторов файлов (буквы, цифры, символ подчеркивания, длина каждого имени до 30 символов);fetch— синхронная функцияfetch(file_id), которая возвращает прочитанные байтыbytes(длиной от 0 до 4096) либо возбуждает исключениеOSError(длина сообщения от 0 до 100 символов);compress— доступная для импорта функцияcompress(file_id, actual_fetched_bytes), возвращающая целочисленную контрольную суммуint;io_pool— инициализированный пул потоковThreadPoolExecutor;cpu_pool— инициализированный пул процессовProcessPoolExecutor.
Функция должна вернуть словарь с двумя ключами: "checksums" и "skipped".
Правила диспетчеризации:
- Сетевое чтение каждого файла должно производиться ровно один раз через
io_poolпутем вызоваfetch(file_id). - Только если сетевое чтение файла завершилось успешно, полученные байты отправляются на сжатие в
cpu_poolчерезcompress(file_id, data). Для успешно прочитанного файла сжатие запускается ровно один раз. - Если сетевое чтение завершилось ошибкой
OSError, задача сжатия для этого файла не создается вообще. В словарьskippedзаписывается строковое представление ошибкиstr(error). - В словаре
checksumsсохраняются парыfile_id: checksumдля всех успешно обработанных файлов. - Порядок ключей в
checksumsиskippedдолжен строго соответствовать исходному относительному порядку идентификаторов в спискеfile_ids. - Если подходящих файлов для какой-либо части нет (или входной список
file_idsпуст), соответствующее значение должно оставаться пустым словарем{}.
Ввод и вывод
Стандартные потоки stdin и stdout не используются: считывать ввод и вызывать print не требуется. Проверяющая система после выполнения кода ученика находит в пространстве имен функцию верхнего уровня archive_files и вызывает её напрямую.
Пример использования
probe = make_archive_probe([('file_a', [65, 65, 66]), ('file_b', [9])], {'file_b': 'storage unavailable'})
print(probe.run()['result'])
Вывод:
{'checksums': {'file_a': 399}, 'skipped': {'file_b': 'storage unavailable'}}
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- ProcessPoolExecutor и lambda: когда возникает ошибка pickle
- ProcessPoolExecutor Python: обработка результатов и ошибок сериализации
- Concurrent.futures Python: первые K успешных результатов двух пулов
- Потоки и процессы Python: аварийная остановка двухэтапного конвейера
- ThreadPoolExecutor и ProcessPoolExecutor: загрузка и обработка данных
- Concurrent.futures Python: выбор исполнителя по размеру пакета
