Python日志记录模块发出错误的时区信息

Ala*_*oni 9 python logging datetime python-2.7

我遇到了Python 2.7日志记录模块的问题.我的系统是Ubuntu 14.04 64bit,我住在意大利(目前UTC + 1,没有夏令时); 系统正确配置.

我想在当前时区发出记录行,完成正确的时区偏移信息.

请考虑以下代码段:

#!/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")
Run Code Online (Sandbox Code Playgroud)

结果如下:

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
Run Code Online (Sandbox Code Playgroud)

因此,系统知道正确的时间和偏移量,而Python似乎错误的时间.

在datetime docs中,据说对于strftime中的%z,结果是"格式为+ HHMM或-HHMM的UTC偏移量(如果对象是天真的,则为空字符串)".

所以,我希望得到以下结果之一:

  1. 记录模块想要以UTC身​​份登录,所以我会得到类似10:21.44和+0000偏移量的东西;
  2. 日志记录模块想要登录本地时间,所以我会得到类似11:21:44和+01000偏移量的东西;
  3. 日志记录模块提供了天真的日期时间对象,我们在偏移量上完全没有.

相反,在这里,我似乎得到了一个不可预测的 - 而且显然是错误的 - 结果.这是怎么回事?是否有可能配置日志模块,做我想做的无覆盖logging.Formatter对象的转换器功能(其中,当然,我可以做任何我喜欢,但是这看起来显然是个错误给我)?

jfs*_*jfs 8

logging使用time不在时间元组中存储时区的模块,而time.strftime()不像Python 2 那样datetime.strftime()不支持%z.您可以覆盖Formatter.formatTime()使用时区感知日期时间对象的方法,而不是@dmg建议:

#!/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')
Run Code Online (Sandbox Code Playgroud)

产量

2015-01-09T18:30:54+0100 something happened
Run Code Online (Sandbox Code Playgroud)


dmg*_*dmg 5

编辑:

您可以通过以下方式设置时间格式器:

logging.Formatter.converter = time.localtime
Run Code Online (Sandbox Code Playgroud)

产生当地时间.

要么:

logging.Formatter.converter = time.gmtime
Run Code Online (Sandbox Code Playgroud)

得到UTC.

至于当地时间+时区,首先,logging.Formatter使用时间,正如你在这里看到的那样,并没有真正支持TZ(请看脚注).

最干净的选择是编写自己使用的格式化程序datetime,这显然有使用TZ 的愚蠢方式.基本上为了使你的对象"意识到",我会选择pytz.