Ведение журнала на Python: использование миллисекунд в формате времени

По умолчанию logging.Formatter('%(asctime)s') печатает в следующем формате:

2011-06-09 10:54:40,638

где 638 - миллисекунда. Мне нужно изменить запятую на точку:

2011-06-09 10:54:40.638

Чтобы отформатировать время, которое я могу использовать:

logging.Formatter(fmt='%(asctime)s',datestr=date_format_str)

однако документация не указывает, как форматировать миллисекунды. Я нашел этот SO вопрос, который говорит о микросекундах, но a) я бы предпочел миллисекунды и b) следующее не работает на Python 2.6 (который я работающий) из-за %f:

logging.Formatter(fmt='%(asctime)s',datefmt='%Y-%m-%d,%H:%M:%S.%f')

Ответ 1

Обратите внимание, решение Крейга Макданиэля явно лучше.


logging.Formatter formatTime метод выглядит следующим образом:

def formatTime(self, record, datefmt=None):
    ct = self.converter(record.created)
    if datefmt:
        s = time.strftime(datefmt, ct)
    else:
        t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
        s = "%s,%03d" % (t, record.msecs)
    return s

Обратите внимание на запятую в "%s,%03d". Это нельзя исправить, указав a datefmt, потому что ct - это time.struct_time, и эти объекты не записывают миллисекунды.

Если мы изменим определение ct, сделав его datetime объектом вместо struct_time, тогда (по крайней мере, с современными версиями Python) мы можем вызвать ct.strftime, а затем мы можем использовать %f для форматирования микросекунд:

import logging
import datetime as dt

class MyFormatter(logging.Formatter):
    converter=dt.datetime.fromtimestamp
    def formatTime(self, record, datefmt=None):
        ct = self.converter(record.created)
        if datefmt:
            s = ct.strftime(datefmt)
        else:
            t = ct.strftime("%Y-%m-%d %H:%M:%S")
            s = "%s,%03d" % (t, record.msecs)
        return s

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

console = logging.StreamHandler()
logger.addHandler(console)

formatter = MyFormatter(fmt='%(asctime)s %(message)s',datefmt='%Y-%m-%d,%H:%M:%S.%f')
console.setFormatter(formatter)

logger.debug('Jackdaws love my big sphinx of quartz.')
# 2011-06-09,07:12:36.553554 Jackdaws love my big sphinx of quartz.

Или, чтобы получить миллисекунды, измените запятую на десятичную точку и опустите аргумент datefmt:

class MyFormatter(logging.Formatter):
    converter=dt.datetime.fromtimestamp
    def formatTime(self, record, datefmt=None):
        ct = self.converter(record.created)
        if datefmt:
            s = ct.strftime(datefmt)
        else:
            t = ct.strftime("%Y-%m-%d %H:%M:%S")
            s = "%s.%03d" % (t, record.msecs)
        return s

...
formatter = MyFormatter(fmt='%(asctime)s %(message)s')
...
logger.debug('Jackdaws love my big sphinx of quartz.')
# 2011-06-09 08:14:38.343 Jackdaws love my big sphinx of quartz.

Ответ 2

Это тоже должно работать:

logging.Formatter(fmt='%(asctime)s.%(msecs)03d',datefmt='%Y-%m-%d,%H:%M:%S')

Ответ 3

После создания a Formatter я обычно устанавливаю formatter.converter = gmtime. Поэтому для того, чтобы @unutbu отвечал на работу в этом случае, вам понадобится:

class MyFormatter(logging.Formatter):
    def formatTime(self, record, datefmt=None):
        ct = self.converter(record.created)
        if datefmt:
            s = time.strftime(datefmt, ct)
        else:
            t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
            s = "%s.%03d" % (t, record.msecs)
        return s

Ответ 4

Самый простой способ, который я нашел, - переопределить default_msec_format:

formatter = logging.Formatter('%(asctime)s')
formatter.default_msec_format = '%s.%03d'