Потоковая запись на Python: ротация файлов и освобождение ресурсов

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

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

Ротация картриджей самописца

Потоковый самописец непрерывно принимает строки замеров из бесконечного источника событий и сохраняет их в съёмный картридж. Ёмкость каждого такого блока строго ограничена и вмещает записей. В процессе работы регистратор удерживает открытым ровно один накопитель за раз.

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

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

Что уже дано

В заготовке объявлена сигнатура функции-генератора rotate_log_records(source, cartridge_factory, capacity) с заглушкой тела. В среде выполнения уже доступны вспомогательный класс накопителя и фабрика проверочных зондов, поэтому реализовывать их заново не требуется.

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

Реализуйте нативный генератор rotate_log_records(source, cartridge_factory, capacity).

Параметры функции:

  • source — бесконечный итератор строковых записей;
  • cartridge_factory — вызываемый объект без аргументов, возвращающий новый открытый картридж с методами write(record) и close();
  • capacity — целое положительное число от 1 до 100, определяющее предельную вместимость одного картриджа.

Правила работы генератора:

  • Генератор должен оставаться полностью ленивым: до первого запроса значения (вызова next()) запрещено запрашивать элементы из source или вызывать cartridge_factory().
  • При каждом шаге генератор запрашивает ровно одну очередную запись из source и записывает её в текущий картридж через вызов write(record).
  • Как только в текущий картридж записано ровно capacity записей, генератор закрывает его вызовом close() и сразу запрашивает новый картридж через cartridge_factory().
  • В процессе записи удерживайте открытым ровно один накопитель. Создание накопителя на замену происходит сразу после закрытия заполненного блока, ещё до того, как генератор отдаст подтверждение текущего шага.
  • После завершения шага записи генератор отдает через yield исходный объект записанной строки в качестве подтверждения.
  • Если потребитель досрочно закрывает генератор (вызовом метода close()), генератор обязан закрыть активный картридж (даже пустой или частично заполненный). Если картридж уже был закрыт, повторный вызов close() безопасен и идемпотентен.

Количество запросов со стороны вызывающего кода не превышает 1000, а длина каждой строки лежит в диапазоне от 0 до 1000 символов.

Ввод и вывод

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

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

probe = make_log_cartridge_probe(['alpha', 'beta'])
stream = rotate_log_records(probe.source, probe.new_cartridge, 2)
print([next(stream) for _ in range(3)])
stream.close()
print([block.records for block in probe.cartridges])

Вывод:

['alpha', 'beta', 'alpha']
[['alpha', 'beta'], ['alpha']]
РешениеPython

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

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

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