2009-05-01 4 views
2

Когда я впервые узнал Python, я привык делать это:Почему пакет протоколов 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)))) 

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

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

ответ

7

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

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

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} 
+0

Обратите внимание, что если вы хотите применить это к регистратору, кроме RootLogger, то вам нужно поставить самозапуск аргумент:. журнала = logging.getLogger («войти») журнала .makeRecord = lambda self, * args: ExtendedLogRecord (self, * args) – Brian

0

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

0

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

1

Ваше заявление о регистрации событий не совсем верно.

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

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


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

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

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

Это смешно, я использую lo в течение многих лет, не зная об этом. Угадайте, что это случай, когда модуль настолько легко подбирается, что я никогда не потрудился посмотреть на документы, где это четко указано. – Kiv

+2

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

2

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

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

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

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

Смежные вопросы