Запретить новую строку в модуле протоколирования Python
Я пытаюсь заменить специальную систему ведения журнала на модуль протоколирования Python. Я использую систему ведения журнала для вывода информации о ходе выполнения для длинной задачи на одной строке, чтобы вы могли tail
регистрировать или просматривать ее в консоли. Я сделал это, указав флаг моей функции регистрации, который подавляет новую строку для этого сообщения журнала и строит строку по частям.
Все протоколирование выполняется из одного потока, поэтому нет проблем с сериализацией.
Возможно ли это сделать с помощью модуля протоколирования Python? Это хорошая идея?
Ответы
Ответ 1
Давайте начнем с вашего последнего вопроса: Нет, я не считаю это хорошей идеей.
IMO, это вредит читабельности файла журнала в долгосрочной перспективе.
Я предлагаю придерживаться модуля logging и использовать опцию '-f' в команде 'tail', чтобы посмотреть результат консоль. Вероятно, вы в конечном итоге используете FileHandler. Обратите внимание, что аргумент по умолчанию для "delay" имеет значение False, поэтому вывод не будет буферизироваться.
Если вам нужно действительно, чтобы подавить новые строки, я бы рекомендовал создать собственный обработчик.
Ответ 2
Если вы хотите сделать это, вы можете изменить терминатор обработчика логов. Я использую Python 3.4. Это было введено в Python 3.2, как заявлено Ninjakannon.
handler = logging.StreamHandler()
handler.terminator = ""
Когда StreamHandler пишет, он пишет терминатор последним.
Ответ 3
Новая строка, \n
, вставлена внутри класса StreamHandler
.
Если вы действительно настроились на исправление этого поведения, вот пример того, как я решил это сделать исправление обезьян emit(self, record)
метод внутри класса logging.StreamHandler.
Патч обезьяны - это способ расширения или изменения кода времени выполнения динамических языков без изменения исходного исходного кода. Этот процесс также был назван перфорированием утки.
Вот пользовательская реализация emit()
, которая опускает разрывы строк:
def customEmit(self, record):
# Monkey patch Emit function to avoid new lines between records
try:
msg = self.format(record)
if not hasattr(types, "UnicodeType"): #if no unicode support...
self.stream.write(msg)
else:
try:
if getattr(self.stream, 'encoding', None) is not None:
self.stream.write(msg.encode(self.stream.encoding))
else:
self.stream.write(msg)
except UnicodeError:
self.stream.write(msg.encode("UTF-8"))
self.flush()
except (KeyboardInterrupt, SystemExit):
raise
except:
self.handleError(record)
Затем вы создадите пользовательский класс ведения журнала (в этом случае, подклассом из TimedRotatingFileHandler
).
class SniffLogHandler(TimedRotatingFileHandler):
def __init__(self, filename, when, interval, backupCount=0,
encoding=None, delay=0, utc=0):
# Monkey patch 'emit' method
setattr(StreamHandler, StreamHandler.emit.__name__, customEmit)
TimedRotatingFileHandler.__init__(self, filename, when, interval,
backupCount, encoding, delay, utc)
Некоторые люди могут утверждать, что этот тип решения не является Pythonic или что-то еще. Это может быть так, поэтому будьте осторожны.
Кроме того, имейте в виду, что это будет глобально патч SteamHandler.emit(...)
, поэтому, если вы используете несколько классов журналов, этот патч также повлияет на другие классы ведения журнала!
Проверьте их для дальнейшего чтения:
Надеюсь, что это поможет.
Ответ 4
Я столкнулся с необходимостью записать определенный раздел в одну строку, когда я перебирал кортеж, но хотел сохранить общий регистратор.
Сначала собрал выходные данные в одну строку, а затем отправил их регистратору, как только я вышел из раздела. Пример концепции
for fld in object._fields:
strX = (' {} --> {} ').format(fld, formattingFunction(getattr(obj,fld)))
debugLine += strX
logger.debug('{}'.format(debugLine))