Генератор пачек Python: подтверждение обработки после yield

Напишите решение на Python и проверьте его на странице.

Другие упражнения по этой теме: Генераторы Python: задачи на ленивые конвейеры и закрытие ресурсов.

Подтверждение пачек замеров

Модуль пакетной отправки читает поток замеров из закрываемого источника и нарезает его на пачки фиксированного размера . Каждая полностью набранная группа отдаётся наружу в виде кортежа. Подтверждение выдачи записывается в журнал источника строго после того, как управление возвращается в генератор на следующем шаге — при запросе новой порции. Поэтому если получатель закрывает генератор сразу после взятия очередной пачки, она остаётся неподтверждённой.

Когда источник штатно исчерпывается по StopIteration, генератор передаёт наружу оставшийся неполный хвост и отмечает статус финализации источника как завершённый. Если же потребитель вызывает close() до того, как генератор физически получил StopIteration, статус фиксации источника должен быть отмечен как досрочно прерванный, даже если данных в источнике больше нет.

Реализуйте генератор пачек, который подтверждает выдачу только при возобновлении и корректно выставляет флаг завершённости источника при его закрытии.

Что уже дано

В среде выполнения доступен класс AcknowledgedSource, предоставляющий итерируемый источник элементов с методами ack(batch) и close(completed: bool). Реализовывать этот класс не нужно: в редакторе требуется написать только функцию-генератор acknowledged_batches.

Что нужно сделать

Реализуйте функцию-генератор acknowledged_batches(source, batch_size).

Функция принимает два аргумента:

  • source — объект источника данных (экземпляр AcknowledgedSource или совместимый тип), являющийся итератором произвольных объектов;
  • batch_size — положительное целое число от 1 до 1000 (включая пользовательские подклассы int), задающее размер полной пачки.

Функция должна возвращать обычный (нативный) ещё не запущенный генератор кортежей-пачек со следующим поведением:

  • Чтение элементов из source выполняется строго по мере необходимости, без забегания вперёд за пределы текущей формируемой пачки. Все элементы и их исходный порядок сохраняются по идентичности.
  • Каждая сформированная полная пачка выдаётся наружу в виде кортежа размера batch_size. Если перед концом потока остался непустой остаток меньшего размера, он также выдаётся наружу в виде кортежа.
  • Метод source.ack(batch) вызывается для выданной пачки строго после того, как внешний потребитель возобновил генератор вызовом next() или send(None). Если потребитель сразу после получения пачки прерывает генератор через close() или throw(), эта пачка подтверждаться не должна.
  • Источник считается завершённым (completed=True), только если генератор реально получил исключение StopIteration от самого source при попытке чтения. Если генератор выдал последнюю полную пачку и был закрыт потребителем до следующего обращения к источнику, StopIteration ещё не произошёл, поэтому статус завершения остаётся False. Если же генератор уже выдал неполный хвост, факт наступления конца потока уже подтверждён, и даже при немедленном вызове close() после хвоста статус финализации считается True.
  • После запуска генератора метод source.close(completed) должен быть вызван ровно один раз в блоке очистки с вычисленным булевым значением флага completed. Если генератор был закрыт потребителем ещё до первого обращения (до первого next()), его тело не выполняется, а source остаётся нетронутым.

Ввод и вывод

Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля функцию верхнего уровня acknowledged_batches и вызывает её с проверочными аргументами.

Пример использования

source = AcknowledgedSource([1, 2, 3])
stream = acknowledged_batches(source, 2)
print(next(stream))
print(source.acknowledgements)
print(next(stream))
print(source.acknowledgements)
stream.close()
print(source.closed, source.close_flags[-1]['completed'])

Вывод:

(1, 2)
[]
(3,)
[(1, 2)]
True True
РешениеPython

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Связанные задачи