Почему пакет журналов python не поддерживает печать аргументов переменной длины? - PullRequest
2 голосов
/ 01 мая 2009

Когда я впервые изучил Python, я привык к этому:

  print "text", lineNumber, "some dictionary", my_dict

Когда я писал свое собственное средство ведения журнала, я, естественно, хотел иметь возможность передать ему список элементов произвольного размера, поэтому я сделал это:

def error(*args):
   print ERR_PREFIX,
   for _x in args:
      print _x,
   print "\r\n",

error("text", lineNumber, "some dictionary", my_dict)

Теперь я хочу начать использовать пакет журналирования, потому что в нем гораздо больше приятных моментов, и мне не хочется копировать их усилия. В целом это выглядит как чистый дизайн, который может многое сделать. Но я зашел в тупик из-за того, что вы больше не можете представить его с тем же списком предметов для печати. Вместо этого я должен изменить все свои звонки на что-то вроде этого:

error("text %d some dictionary %s" % (lineNumber, my_dict))

Или я мог бы сделать что-то действительно глупое, как это:

error(' '.join(map, str(("text", lineNumber, "some dictionary", my_dict))))

Вопрос в том, почему опускают такой очевидный вариант использования? Если вы хотите перейти от типичного оператора «print» прямо к новомодному средству ведения журнала, разве это не должно быть проще?

В качестве дополнительного вопроса, можете ли вы придумать способ переопределить класс Logger для выполнения этого?

Ответы [ 5 ]

7 голосов
/ 01 мая 2009

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

Кстати, следующий код заставит модуль логирования работать так, как вы хотите.

import logging
import types

class ExtendedLogRecord(logging.LogRecord):

    def getMessage(self):
        """
        Return the message for this LogRecord.

        Return the message for this LogRecord after merging any user-supplied
        arguments with the message.
        """
        if not hasattr(types, "UnicodeType"): #if no unicode support...
            msg = str(self.msg)
        else:
            try:
                msg = str(self.msg)
            except UnicodeError:
                msg = self.msg      #Defer encoding till later
        if self.args:
            msg +=' '+' '.join(map(str,self.args))
        return msg

#Patch the logging default logging class
logging.RootLogger.makeRecord=lambda self,*args: ExtendedLogRecord(*args)

some_dict={'foo':14,'bar':15}
logging.error('text',15,'some dictionary',some_dict)

Выход:

ERROR:root:text 15 some dictionary {'foo': 14, 'bar': 15}
2 голосов
/ 02 мая 2009

Исправление пакета журнала (как рекомендовано одним ответом) на самом деле плохая идея, потому что это означает, что другой код (который вы не написали, например, материал в стандартной библиотеке), который вызывает ведение журнала. Ошибка () больше не будет работать правильно.

Вместо этого вы можете изменить существующую функцию error (), чтобы вместо нее вызывать logging.error (), или вывести:

def error(*args):
  logging.error('%s', ' '.join(map(str, args)))

(Если могут быть объекты в юникоде, вам нужно быть немного более осторожным, но вы поймете идею.)

1 голос
/ 01 мая 2009

Ваше утверждение о регистрации не полностью верно.

log= logging.getLogger( "some.logger" )
log.info( "%s %d", "test", value )
log.error("text %d some dictionary %s", lineNumber, my_dict) 

Вам не нужно явно использовать оператор форматирования строки, %


Редактировать

Вы можете использовать свою оригинальную функцию "error".

def error( *args ):
    log.error( " ".join( map( str, args ) ) )

Что, вероятно, сделает переход менее сложным.

Вы также можете сделать это.

class MyErrorMessageHandler( object ):
    def __init__( self, logger ):
        self.log= logger
    def __call__( self, *args ):
        self.log.error( " ".join( map( str, args ) ) )
error= MyErrorMessageHandler( logging.getLogger("some.name") )

Что также может быть приемлемым.

0 голосов
/ 01 мая 2009

Относительно легко добавить метод в класс динамически. Почему бы просто не добавить свой метод в журнал.

0 голосов
/ 01 мая 2009

Ну, печать и логирование - это две разные вещи. Само собой разумеется, что как таковое их использование также может быть совершенно другим.

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