Генераторы Python: закройте второй источник при ошибке первого
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Генераторы Python: задачи на ленивые конвейеры и закрытие ресурсов.
Синхронизатор каналов датчиков
Модуль безопасности следит за давлением с помощью двух независимых датчиков, опрашивая их генераторные потоки парами. На каждом шаге координатор считывает замер сначала из первичного канала, а затем из вторичного. Если оба значения получены без сбоев, генератор выдаёт наружу готовую пару (primary_val, secondary_val).
Если любой из двух каналов при очередном чтении выбрасывает исключение, синхронизатор обязан немедленно вызвать метод close() у оставшегося неповреждённого потока, если чтение из него уже успело начаться, и только после этого повторно выбросить исходную ошибку. Когда же любой канал штатно исчерпывает данные по StopIteration либо сам синхронизатор досрочно закрывается через собственный close(), координатор закрывает оба активных потока.
Реализуйте генератор парного чтения, который выдаёт замеры в строгом порядке, надёжно обесточивает активный парный источник перед пробросом сбоя и гарантированно закрывает оба канала при остановке работы.
Что уже дано
В среде выполнения доступны вспомогательные инструменты make_channel_probe и observe_paired_channels для создания тестовых каналов и отслеживания их жизненного цикла. Реализовывать их заново не требуется: вам нужно написать только саму функцию pair_channels.
Что нужно сделать
Реализуйте функцию-генератор pair_channels(primary, secondary).
Функция принимает два аргумента:
primary— однократный итератор первого канала;secondary— однократный итератор второго канала.
Каждый источник представляет собой генераторный поток, поддерживающий методы протокола итератора (__iter__, __next__) и метод close(). Каждый поток содержит от 0 до 1000 замеров (конечные целые или вещественные числа в диапазоне от -1 000 000 до 1 000 000). Метод close() у источников идемпотенvariableтен и не возбуждает исключений. При чтении очередного элемента любой канал может выбросить произвольное исключение (включая прямые подклассы BaseException).
Функция должна возвращать неначатный нативный генератор Python, выдающий кортежи замеров вида (primary_val, secondary_val).
Правила работы координатора:
- Создание генератора происходит лениво и не выполняет чтений из каналов. Если созданный генератор закрывается вызовом собственного метода
close()до первого запроса значения, он не входит в своё тело, не начинает опрос и не вызываетclose()у входных источников. - Чтение выполняется строго по требованию: сначала опрашивается
primary, и только при успехе —secondary. Каждая полученная пара значений без изменений выдаётся наружу в виде кортежа. Никакой фильтрации пар производиться не должно. - Если любой из каналов завершается по
StopIteration, генератор немедленно прекращает работу, строго сохраняя порядок обращения кprimaryпередsecondary, и не запрашивает последующие пары. - Если при чтении из канала возникает ошибка, синхронизатор обязан вызвать метод
close()у второго канала, если работа с ним уже была начата, после чего повторно выбросить ровно тот же самый объект исключения без подмены. - При нормальном завершении конвейера или досрочном закрытии генератора потребителем через
close()все активные потоки должны быть финализированы. Неначатый канал закрывать не нужно. - После выполнения очистки координатор не должен совершать никаких новых попыток чтения из каналов, в том числе попыток с перехватом исключений.
Ввод и вывод
Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля функцию верхнего уровня pair_channels и вызывает её с проверочными аргументами.
Пример использования
probe = make_channel_probe([1, 2, 3], [10, 20])
print(list(pair_channels(probe.primary, probe.secondary)))
Вывод:
[(1, 10), (2, 20)]
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- GeneratorExit и yield при close(): вопрос по генераторам Python
- Генераторы Python: синхронизация потоков после фильтрации
- Генераторы Python: разделите поток между двумя потребителями
- Исправьте остановку генераторного конвейера Python
- Генератор скользящего среднего на Python со сбросом окна
- Фильтрация потока Python: исключения и гарантированное закрытие генератора
