Ограничить размер выходного файла Python - PullRequest
2 голосов
/ 16 июня 2011

У меня есть программа на Python, запущенная в Debian, которая выводит данные, используя объект File. Я хотел бы установить ограничение на размер моего файла, но я не хочу останавливать запись файла - я просто хочу удалить самую старую строку (вверху файла). Мои данные записываются случайным образом по мере поступления пакетов от клиентов (например, веб-журналы).

Я знаю, что это работает, но было бы в моих интересах проверить это, используя комбинацию File.tell () и затем выполнив следующую системную команду, если мой файл превышает ограничение?

sed -i '1 d' filename 

Как только он достигнет предела размера, он будет выполнять sed каждый раз. Есть ли лучший способ?

Ответы [ 5 ]

3 голосов
/ 16 июня 2011

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

Обычная стратегия - начинать запись в новый файл, когда текущий становится слишком большим.Затем вы можете удалить файлы, которые старше, чем порог.Это «ротация журналов», о которой упоминали другие.

Если вы действительно хотите создать очередь, в которой вы удаляете одну строку данных при добавлении новой, я бы предложил вместо этого использовать базу данных.MongoDB и другие менеджеры баз данных поддерживают массивы, но при необходимости вы можете сделать нечто подобное с базой данных SQL.

2 голосов
/ 16 июня 2011

Причина, по которой модуль журналирования Python не использует эту стратегию, заключается в снижении производительности, которое оно влечет за собой. Если файлы журнала, повернутые в соответствии с размером или возрастом, просто неприемлемы, то, на мой взгляд, у вас есть два основных варианта: перезаписать файл журнала на месте, записать временный файл и заменить.

Если перезаписать файл журнала на месте, вы сначала должны выбрать в файле целочисленный адрес (позиция первого \ n байта плюс один), который станет «новым нулем» (назовите его X). Затем выберите размер блока, может быть 32K. Тогда начни считать. Искать в X + размер блока * номер блока, читать один блок. Искать размер блока * номер блока, записывать блок обратно. Когда вы достигнете EOF при чтении, обрежьте файл до размера блока длины * номер блока.

Если используется временный файл, найдите «новый ноль», скопируйте оставшуюся часть файла во временный файл, а затем переименуйте его в исходное имя. Я полагаю, это проще, чем выше, легче объяснить, но занимает больше места.

После всего этого запишите новые данные и закройте файл. Вся эта процедура должна происходить для каждого сообщения журнала. Удачи!

2 голосов
/ 16 июня 2011

Кажется, вы не знаете logrotate.Вы ищете аналогичную реализацию.Проверьте это:

1 голос
/ 16 июня 2011

Вы должны проверить Модуль регистрации Python и, более конкретно, класс RotatingFileHandler . Это позволяет вам записывать в файл, который будет иметь фиксированный размер. Однако он не позволяет работать с количеством строк.

0 голосов
/ 16 июня 2011

Если вам не нужен доступ к файлу в реальном времени из другого процесса, я, вероятно, записал бы каждую строку журнала в collections.deque фиксированного размера.Вы можете реализовать метод, который будет синхронизировать элементы (строки) из collections.deque со строками в файле журнала по запросу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...