Журнал Python: использовать миллисекунды в формате времени - PullRequest
134 голосов
/ 09 июня 2011

По умолчанию 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 вопрос , который говорит о микросекундах, но а) я бы предпочел миллисекунды и б) следующее не работает на Python 2.6 (над которым я работаю) из-за %f:

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

Ответы [ 7 ]

271 голосов
/ 22 сентября 2011

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

logging.Formatter(fmt='%(asctime)s.%(msecs)03d',datefmt='%Y-%m-%d,%H:%M:%S')
64 голосов
/ 09 июня 2011

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


logging.Formatter's 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". Это нельзя исправить, указав 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.
13 голосов
/ 12 марта 2018

Добавление msecs было лучшим вариантом, спасибо.Вот моя поправка, использующая это с Python 3.5.3 в Blender

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s.%(msecs)03d %(levelname)s:\t%(message)s', datefmt='%Y-%m-%d %H:%M:%S')
log = logging.getLogger(__name__)
log.info("Logging Info")
log.debug("Logging Debug")
11 голосов
/ 26 февраля 2017

Я нашел самый простой способ переопределить default_msec_format:

formatter = logging.Formatter('%(asctime)s')
formatter.default_msec_format = '%s.%03d'
4 голосов
/ 18 января 2012

После создания 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
2 голосов
/ 11 января 2018

Простое расширение, которое не требует модуля datetime и не имеет недостатков, как некоторые другие решения, заключается в использовании простой замены строки, например:

import logging
import time

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

Таким образом, формат даты может быть записан так, как вы хотите, даже с учетом различий по регионам, используя %F для миллисекунд. Например:

log = logging.getLogger(__name__)
log.setLevel(logging.INFO)

sh = logging.StreamHandler()
log.addHandler(sh)

fm = MyFormatter(fmt='%(asctime)s-%(levelname)s-%(message)s',datefmt='%H:%M:%S.%F')
sh.setFormatter(fm)

log.info("Foo, Bar, Baz")
# 03:26:33.757-INFO-Foo, Bar, Baz
1 голос
/ 03 марта 2018

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

import logging

from arrow.arrow import Arrow


class ArrowTimeFormatter(logging.Formatter):

    def formatTime(self, record, datefmt=None):
        arrow_time = Arrow.fromtimestamp(record.created)

        if datefmt:
            arrow_time = arrow_time.format(datefmt)

        return str(arrow_time)


logger = logging.getLogger(__name__)

default_handler = logging.StreamHandler()
default_handler.setFormatter(ArrowTimeFormatter(
    fmt='%(asctime)s',
    datefmt='YYYY-MM-DD HH:mm:ss.SSS'
))

logger.setLevel(logging.DEBUG)
logger.addHandler(default_handler)

Теперь вы можете использовать все форматирование времени стрелки в атрибуте datefmt.

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