Подтвердить что ты не робот

Запретить новую строку в модуле протоколирования Python

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

Все протоколирование выполняется из одного потока, поэтому нет проблем с сериализацией.

Возможно ли это сделать с помощью модуля протоколирования Python? Это хорошая идея?

4b9b3361

Ответ 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))