El módulo de registro de Python emite información de zona horaria incorrecta

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:

  1. El módulo de registro desea iniciar sesión en UTC, así que obtendría algo como 10: 21.44 y un desplazamiento de +0000;
  2. El módulo de registro desea iniciar sesión en la hora local, así que obtendría algo como 11:21:44 y un desplazamiento de +01000;
  3. El módulo de registro ofrece objetos de fecha y hora ingenuos, y no obtenemos absolutamente nada como en el desplazamiento.

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') 

Salida

 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 .