#python #logging #output-buffering
#python #ведение журнала #вывод-буферизация
Вопрос:
Классы logging
обработчиков имеют метод flush() .
И, глядя на код, logging.FileHandler
не передает определенный режим буферизации при вызове open()
. Поэтому при записи в файл журнала он будет буферизоваться с использованием размера блока по умолчанию.
Это правильно?
Меня это удивляет, потому что, когда я управляю своей собственной системой, я привык просматривать файлы журналов в режиме реального времени (или почти в режиме реального времени) в системе. Для этого варианта использования требуется буферизация строк. Кроме того, традиционный системный журнал () для демона ведения журнала не буферизует сообщения.
Меня интересуют версии Python 2.7 и 3.7.
Комментарии:
1. Небольшое замечание о
stderr
том, что при tty он, как правило, по умолчанию не буферизуется, в отличие от стандартного вывода, который обычно по умолчанию буферизуется строками. Понятия не имею оsystemd
/journald
, но я бы предположил, что имело бы смысл изменить буферизацию любогоstderr
захвата / перенаправления на одинаковую (небуферизованную).2. @OndrejK. ответ на мой вопрос «нет» — я неправильно прочитал код, я его запишу. Что касается буферизации stderr, я думаю, что python3 обладает удивительным поведением. Я исходил из документа, в котором говорится, что он может быть буферизован блоками, и я думаю, что документ точен. Подробнее об этом в этом выпуске python .
3. Да, я посмотрел на базовый код … режим py2.7
a
будет в основном тем, что ваша система будет делать дляopenat
вызова. py3.xa
— текстовый режим, поэтому вы получите буферизованный текстовый ввод-вывод (не в блоке tty, по умолчанию в строке tty), дескриптор файла нижеopenat
такой же (за исключением|O_CLOEXEC
, «не наследуемый» fd по существу), но буферизация происходит изio
модуля.
Ответ №1:
Не совсем. Он будет очищать каждое отдельное сообщение, чего вы и хотите.
FileHandler наследует от StreamHandler . StreamHandler вызывает self.flush() после каждой записи () в поток.
Метод flush() начинает иметь больше смысла, если вы посмотрите на logging.MemoryHandler
него. Для программ, которые хотят добавить буферизацию, MemoryHandler позволяет обернуть другой обработчик и буферизировать заданное количество сообщений. Он также будет немедленно сбрасываться при получении сообщений выше установленного уровня серьезности. logging
не включает обработчик, который автоматически сбрасывается каждую секунду или около того, но вы всегда можете написать его самостоятельно.
Вызовы flush в StreamHandler также означают, что он делает то, что вы хотите, если ваша программа запускается как systemd
служба и вы входите в stderr
нее. В этом случае Python 3 требует сброса. Python 3 в настоящее время использует буферизацию блоков для stderr, когда это не TTY. См . Обсуждение проблемы Python 13597
Возможная причина моей ошибки
Я думаю, что меня смутил код StreamHandler. Если пользователю никогда не нужно было вызывать метод flush(), зачем StreamHandler определять непустую, публично документированную реализацию?
Я думаю, что я слишком много предполагал, и я не учитывал, как здесь используется наследование (argh). Например. базовый класс обработчика имеет пустой метод flush() , но StreamHandler не хочет его наследовать, потому что у него странная строка документа «Эта версия ничего не делает и предназначенабудет реализовано подклассами «.