Estoy encontrando un problema con el módulo de registro de Python 2.7. Mi sistema es Ubuntu 14.04 64bit, y vivo en Italia (actualmente UTC + 1, sin horario de verano); El sistema está correctamente configurado como tal.
Quiero emitir líneas de registro en la zona horaria actual, completa de la información de compensación de zona horaria correcta.
Considere el siguiente fragmento de código:
#!/usr/bin/env python import sys print sys.version_info import commands print "System time: %s" % commands.getoutput("date --rfc-3339=seconds") import logging import datetime logging.basicConfig(level=logging.DEBUG, stream=sys.stdout, format="%(asctime)s:" + logging.BASIC_FORMAT, datefmt="%Y-%m-%dT%H:%M:%S%z") logger = logging.getLogger() logger.info("Something happened")
Lo que da este resultado:
sys.version_info(major=2, minor=7, micro=6, releaselevel='final', serial=0) System time: 2015-01-09 11:21:44+01:00 2015-01-09T11:21:44+0000:INFO:root:Something happened
Por lo tanto, el sistema conoce el tiempo y el desplazamiento adecuados, mientras que Python parece equivocarse.
En documentos de fecha y hora, se dice que para% z en tiempo de ejecución el resultado es “Desfase UTC en la forma + HHMM o -HHMM (cadena vacía si el objeto es ingenuo)”.
Por lo tanto, habría esperado cualquiera de los siguientes resultados:
Por el contrario, aquí parece que obtengo un resultado impredecible, y claramente erróneo. ¿Que pasa? ¿Es posible configurar el módulo de registro para hacer lo que quiero SIN anular la función de conversión del registro? Objetos de formateo (donde, por supuesto, puedo hacer lo que quiera, pero me parece un error).
logging
usa un módulo de time
que no almacena la zona horaria en una tupla de tiempo y time.strftime()
diferencia de que datetime.strftime()
no admite %z
en Python 2. Podría anular el método Formatter.formatTime()
para usar la zona horaria objetos datetime como @dmg sugirió en su lugar:
#!/usr/bin/env python import logging from datetime import datetime import tzlocal # $ pip install tzlocal def posix2local(timestamp, tz=tzlocal.get_localzone()): """Seconds since the epoch -> local time as an aware datetime object.""" return datetime.fromtimestamp(timestamp, tz) class Formatter(logging.Formatter): def converter(self, timestamp): return posix2local(timestamp) def formatTime(self, record, datefmt=None): dt = self.converter(record.created) if datefmt: s = dt.strftime(datefmt) else: t = dt.strftime(self.default_time_format) s = self.default_msec_format % (t, record.msecs) return s logger = logging.getLogger(__name__) handler = logging.StreamHandler() handler.setFormatter(Formatter("%(asctime)s %(message)s", "%Y-%m-%dT%H:%M:%S%z")) logger.addHandler(handler) logger.setLevel(logging.DEBUG) logger.info('something happened')
2015-01-09T18:30:54+0100 something happened
EDITAR:
Puede configurar el formateador de tiempo por:
logging.Formatter.converter = time.localtime
para dar la hora local.
O:
logging.Formatter.converter = time.gmtime
para obtener UTC.
En cuanto a la hora local + zona horaria, en primer lugar, el logging.Formatter
. La información del logging.Formatter
utiliza la hora, que como se puede ver aquí no es compatible con TZ correctamente (consulte la nota al pie de página).
La alternativa más limpia sería escribir tu propio formateador que usa datetime
, que aparentemente tiene una forma bastante estúpida de usar TZ. Básicamente, para hacer que tu objeto sea “consciente”, me gustaría ir con pytz .