Генераторы Python: объединение закрываемых источников данных
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Генераторы Python: задачи на ленивые конвейеры и закрытие ресурсов.
Сквозной генератор сегментов архива
Потоковый считыватель архива разбирает данные по цепочке независимых файлов-сегментов, каждый из которых оформлен собственным закрываемым итератором. В начале каждой сессии источник выдаёт строковый заголовок, а следом за ним — серию числовых замеров. Задача главного генератора — принимать эти порции и отдавать потребителю сплошной плоский поток чисел.
При переходе от одного файла к следующему конвейер обязан аккуратно закрывать завершившийся итератор и проверять, что новый сегмент открылся без сбоев. В каждый момент времени открытым может оставаться только один текущий ресурс: пока данные читаются из активного файла, следующие сегменты из общего списка не должны инициироваться заранее.
Если же внешний потребитель решает прервать обработку и досрочно вызывает close(), генератор должен освободить ровно тот сегмент, на котором остановилось чтение, оставив нетронутыми все последующие нераспакованные источники. Реализуйте этот генератор сквозного чтения с безопасным поэтапным управлением файловыми ресурсами.
Что уже дано
В среде выполнения доступны вспомогательный класс ArchiveSegment и функция make_segment_chain_probe(segments) для создания фабрик сегментов. Реализовывать их заново не требуется: вам нужно написать только генераторную функцию stream_segments.
Что нужно сделать
Реализуйте функцию-генератор stream_segments(segment_factories).
Функция принимает список segment_factories (от 0 до 100 элементов), состоящий из функций без аргументов. Каждый вызов фабрики открывает новый закрываемый итератор сегмента архива: первое значение в нём — строковый заголовок сессии, а все последующие — конечные числовые значения (типы int, float, включая bool, в диапазоне от -1 000 000 до 1 000 000). Общее количество замеров во всех сегментах составляет от 0 до 1000.
Правила потоковой обработки:
stream_segmentsдолжен быть нативным генератором Python. До первого запроса значения черезnext()ни одна фабрика не должна вызываться, и ни один ресурс сегмента не должен открываться.- Очередной сегмент открывается строго в момент, когда генератору необходимо получить из него данные. Сразу после открытия сегмента необходимо прочитать его первый элемент — заголовок сессии — и отбросить его, не отдавая наружу.
- Все последующие числовые замеры из текущего сегмента выдаются наружу через
yieldв исходном порядке. - Допустимы сегменты, содержащие только заголовок и ни одного замера. В этом случае генератор переходит к следующему сегменту цепочки.
- Перед открытием следующего сегмента предыдущий сегмент должен быть гарантированно закрыт вызовом его метода
close(). В любой момент времени открытым может быть не более одного сегмента. - При полном исчерпании всех сегментов каждый открытый сегмент должен оказаться закрытым.
- Если потребитель досрочно закрывает сам генератор вызовом
close()(в том числе до первого шагаnext()), генератор обязан закрыть текущий открытый сегмент (если он успел открыться) и завершить работу. Будущие фабрики из спискаsegment_factoriesпри этом вызываться не должны.
Ввод и вывод
Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля функцию верхнего уровня stream_segments и вызывает её с проверочными аргументами.
Пример использования
probe = make_segment_chain_probe([[1, 2], [], [3]])
stream = stream_segments(probe.factories)
print(next(stream))
print(list(stream))
print([segment.closed for segment in probe.segments])
Вывод:
1
[2, 3]
[True, True, True]
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- GeneratorExit и yield при close(): вопрос по генераторам Python
- Генераторы Python: синхронизация потоков после фильтрации
- Генераторы Python: разделите поток между двумя потребителями
- Исправьте остановку генераторного конвейера Python
- Генератор скользящего среднего на Python со сбросом окна
- Генераторы Python: закройте второй источник при ошибке первого
