2011-06-09 15 views
96

Por defecto logging.Formatter('%(asctime)s') impresiones con el siguiente formato:Python registro: uso milisegundos en formato de hora

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

donde 638 es la milésima de segundo. Necesito cambiar la coma a un punto:

2011-06-09 10:54:40.638 

Para dar formato a la vez que puede utilizar:

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

sin embargo el documentation no especifica cómo formatear milisegundos. He encontrado this SO question que habla de microsegundos, pero a) yo preferiría milisegundos y b) el siguiente no funciona en Python 2.6 (que estoy trabajando) debido a la %f:

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

¿Tal vez cambiar la configuración regional podría ayudar? – pajton

+1

@ pajton - en el siguiente enlace dice "La información de configuración regional no es utilizada por asctime()" - http://docs.python.org/library/time.html#time.asctime – Jonathan

+0

'% f' no funciona en python 2.7.9 o 3.5.1 ya sea –

Respuesta

44

Tenga en cuenta Craig McDaniel's solution es claramente mejor.


método de logging.Formatter formatTime se 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 

Aviso la coma en "%s,%03d". Esto no se puede solucionar especificando un datefmt porque ct es un time.struct_time y estos objetos no registran milisegundos.

Si cambiamos la definición de ct para que sea un objeto datetime en lugar de un struct_time, entonces (al menos con las versiones modernas de Python) podemos llamar ct.strftime y entonces podemos utilizar %f a microsegundos formato:

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, cambiar la coma a un punto decimal, y omitir el argumento 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. 
+0

entonces% f en realidad daría microsegundos, no milisegundos, ¿verdad? – Jonathan

+0

@Jonathan: oops, tienes razón, '% f' da microsegundos. Supongo que la manera más fácil de obtener milisegundos es cambiar la coma a un punto decimal (ver edición arriba). – unutbu

+2

Quiero +1 otra vez si pudiera, gracias por su actualización :) – Jonathan

211

Esto debería funcionar también:

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

Gracias: Aquí están los documentos para esto: https://docs.python.org/2/library/logging.html#logrecord-attributes https: //docs.python.org/3/library/logging.html#logrecord-attributes. ¿Hay alguna manera de incluir aún la zona horaria (% z)? ... Los tiempos de formato ISO8601 en los registros de Python (, ->.) Serían geniales. –

+4

Esta solución está restringida, porque si tiene '% z' o'% Z' en su 'datefmt' quiere que aparezca DESPUÉS de los msecs, no antes. – wim

+0

Y también si está utilizando un reloj de 12 horas que tiene 'AM' o' PM' –

4

Después de crear instancias de un Formatter lo general puse formatter.converter = gmtime. Así que para que la respuesta de @ unutbu para trabajar en este caso se necesita:

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

La forma más sencilla que encontré fue para anular default_msec_format:

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

Interesante, gracias. Pero esto no funcionó para mí en Python 2.7. Es posible que solo funcione en Python 3.x para algún valor de x. – nealmcb

1

Una expansión simple que no requiere la datetime módulo y no se ve obstaculizada como algunas otras soluciones es el uso de sustitución de cadenas simples de este modo:

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 

esta manera un formato de fecha se puede escribir sin embargo que wan t, incluso teniendo en cuenta las diferencias de región, utilizando %F durante milisegundos.Por ejemplo:

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 
0

Si está utilizando arrow o si no les importa usar la flecha. Puede sustituir el formato de hora de python por el de flecha.

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) 

Ahora se puede utilizar en todos arrow's time formattingdatefmt atributo.

Cuestiones relacionadas