Registro de Python: use milisegundos en formato de hora

Resuelto Jonathan Livni asked hace 13 años • 17 respuestas

Por defecto logging.Formatter('%(asctime)s')imprime con el siguiente formato:

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

donde 638 es el milisegundo. Necesito cambiar la coma por un punto:

2011-06-09 10:54:40.638

Para formatear la hora puedo usar:

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

sin embargo, la documentación no especifica cómo formatear los milisegundos. Encontré esta pregunta SO que habla de microsegundos, pero a) preferiría milisegundos yb) lo siguiente no funciona en Python 2.6 (en el que estoy trabajando) debido a %f:

logging.Formatter(fmt='%(asctime)s',datefmt='%Y-%m-%d,%H:%M:%S.%f')
Jonathan Livni avatar Jun 09 '11 16:06 Jonathan Livni
Aceptado

Esto también debería funcionar:

logging.Formatter(
    fmt='%(asctime)s.%(msecs)03d',
    datefmt='%Y-%m-%d,%H:%M:%S'
)
Craig McDaniel avatar Sep 22 '2011 15:09 Craig McDaniel

Tenga en cuenta que es preferible la solución de Craig McDaniel , a menos que necesite compatibilidad con todos los códigos de formato ISO 8601.


El método logging.Formatter formatTimese ve así:

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

Observe la coma en "%s,%03d". Esto no se puede solucionar especificando a datefmtporque ctes a time.struct_timey estos objetos no registran milisegundos.

Si cambiamos la definición de ctpara convertirlo en un datetimeobjeto en lugar de un struct_time, entonces (al menos con las versiones modernas de Python) podemos llamar ct.strftimey luego podemos usar %fpara formatear microsegundos:

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.

O, para obtener milisegundos, cambie la coma a un punto decimal y omita el datefmtargumento:

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.
unutbu avatar Jun 09 '2011 09:06 unutbu