Форматирование строки журнала python
Я использую журнал python formatter для форматирования записей журнала и я имеет значение fmt
fmt = "[%(filename)s:%(lineno)s] %(message)s"
Я бы хотел, чтобы "[file.py:20]" растягивался до 10 символов (например). Если бы это было одно значение, это было бы легко, но есть ли способ растянуть всю эту структуру до определенной длины?
Мне нужно что-то вроде:
tmp = "[%(filename)s:%(lineno)s]"
fmt = "%(tmp)10s %(message)s"
Я хотел бы знать, возможно ли это, используя форматирование строк, или если я могу как-то обмануть форматировщик python, чтобы получить то, что я хочу.
Ответы
Ответ 1
Вариант 1
Начните здесь: http://docs.python.org/library/logging.html#formatter-objects
Вы создадите свой собственный подклассом Formatter
, который предоставит ему собственный уникальный метод format
.
Затем вы должны обязательно позвонить setFormatter()
в каждом из ваших Handlers
, чтобы они использовали ваш новый форматтер.
Вариант 2
Создайте свой собственный подкласс LogRecord с дополнительным свойством.
Подкласс Logger
и переопределить makeRecord
, чтобы создать новый подкласс LogRecord
.
Предоставить настраиваемый формат, который использует это новое значение свойства.
Ответ 2
В качестве примера этот Formatter обеспечивает фиксированную ширину "[%(filename)s:%(lineno)s]"
путем обрезания имени файла или правого заполнения (после номера строки) с пробелами.
class MyFormatter(logging.Formatter):
width = 10
def format(self, record):
max_filename_width = self.width - 3 - len(str(record.lineno))
filename = record.filename
if len(record.filename) > max_filename_width:
filename = record.filename[:max_filename_width]
a = "%s:%s" % (filename, record.lineno)
return "[%s] %s" % (a.ljust(self.width), record.msg)
if __name__ == '__main__':
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = MyFormatter()
ch.setFormatter(formatter)
logger.addHandler(ch)
logger.debug('No one expects the spammish repetition')
EDIT:
Если вы хотите обеспечить минимальную ширину в 10 символов, пропустите файл.
def format(self, record):
a = "%s:%s" % (record.filename, record.lineno)
return "[%s] %s" % (a.ljust(self.width), record.msg)
Ответ 3
Используя @rob-cowie ответ в качестве основы, я нашел следующее полезным:
class MyFormatter(logging.Formatter):
width = 24
datefmt='%Y-%m-%d %H:%M:%S'
def format(self, record):
cpath = '%s:%s:%s' % (record.module, record.funcName, record.lineno)
cpath = cpath[-self.width:].ljust(self.width)
record.message = record.getMessage()
s = "%-7s %s %s : %s" % (record.levelname, self.formatTime(record, self.datefmt), cpath, record.getMessage())
if record.exc_info:
# Cache the traceback text to avoid converting it multiple times
# (it constant anyway)
if not record.exc_text:
record.exc_text = self.formatException(record.exc_info)
if record.exc_text:
if s[-1:] != "\n":
s = s + "\n"
s = s + record.exc_text
#if record.stack_info:
# if s[-1:] != "\n":
# s = s + "\n"
# s = s + self.formatStack(record.stack_info)
return s
logFormatter = MyFormatter()
logger = logging.getLogger("example")
logger.setFormatter(logFormatter)
Что дает вывод, например:
WARNING 2014-03-28 16:05:09 module:function:31 : Message
WARNING 2014-03-28 16:05:09 dule:longerfunctions:140 : Message