如何更改Python日志记录中的时区?

25m*_*mhz 12 python-2.7 audit-logging

我想更改日志文件中的时间戳,以便它反映我当前的时区,以便我可以更快的速度调试错误,

我可以更改日志文件中的时区吗?

目前我的配置是:

logging.basicConfig(filename='audit.log',
                filemode='w',
                level=logging.INFO,
                format='%(asctime)s %(message)s',
                datefmt='%m/%d/%Y %I:%M:%S %p')
Run Code Online (Sandbox Code Playgroud)

小智 10

#!/usr/bin/python

from datetime import datetime
from pytz import timezone
import logging

def timetz(*args):
    return datetime.now(tz).timetuple()

tz = timezone('Asia/Shanghai') # UTC, Asia/Shanghai, Europe/Berlin

logging.Formatter.converter = timetz

logging.basicConfig(
    format="%(asctime)s %(levelname)s: %(message)s",
    level=logging.INFO,
    datefmt="%Y-%m-%d %H:%M:%S",
)

logging.info('Timezone: ' + str(tz))
Run Code Online (Sandbox Code Playgroud)

使用 pytz 定义相对于 UTC 的时区。
基于示例:secsilm


Rya*_*all 9

#!/usr/bin/env python
from datetime import datetime
import logging
import time

from pytz import timezone, utc


def main():
    logging.basicConfig(format="%(asctime)s %(message)s",
                        datefmt="%Y-%m-%d %H:%M:%S")
    logger = logging.getLogger(__name__)
    logger.error("default")

    logging.Formatter.converter = time.localtime
    logger.error("localtime")

    logging.Formatter.converter = time.gmtime
    logger.error("gmtime")

    def customTime(*args):
        utc_dt = utc.localize(datetime.utcnow())
        my_tz = timezone("US/Eastern")
        converted = utc_dt.astimezone(my_tz)
        return converted.timetuple()

    logging.Formatter.converter = customTime
    logger.error("customTime")

    # to find the string code for your desired tz...
    # print(pytz.all_timezones)
    # print(pytz.common_timezones)


if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)
  • 表面上看,pytz包是在Python中转换时区的有福方式.所以我们从datetime转换开始,然后获取(immutable)time_tuple匹配time方法的返回类型
  • logging.Formatter.converter此答案建议设置该功能:( Python日志记录:如何设置GMT时间).
  • 通过取消注释结束行找到您最喜欢的TZ代码


Isa*_*aac 8

只需将此pythonic行添加到您的代码中(使用pytz和datetime):

from pytz import timezone
from datetime import datetime

logging.Formatter.converter = lambda *args: datetime.now(tz=timezone('tz string name')).timetuple()

# quoting Ryan J McCall: to find the string name for your desired timezone...
# print(pytz.all_timezones)
# or print(pytz.common_timezones)
Run Code Online (Sandbox Code Playgroud)


Wyr*_*ood 6

如何记录时区

%Zstrftime格式

视窗

>>> import logging
>>> logging.basicConfig(format="%(asctime)s %(message)s", datefmt="%m/%d/%Y %I:%M:%S %p %Z")
>>> logging.error('test')
11/03/2017 02:29:54 PM Mountain Daylight Time test
Run Code Online (Sandbox Code Playgroud)

的Linux

>>> import logging
>>> logging.basicConfig(format="%(asctime)s %(message)s", datefmt="%m/%d/%Y %I:%M:%S %p %Z")
>>> logging.error('test')
11/03/2017 02:30:50 PM MDT test
Run Code Online (Sandbox Code Playgroud)

如果问题是

如何登录与服务器本地时间不同的时区?

答案的一部分是logging.Formatter.converter,但是,您必须了解幼稚的日期时间对象。除非您想编写自己的时区模块,否则我强烈建议使用pytz库(pip install pytz)。Python 3包含UTC和UTC偏移时区,但是对于夏时制或其他偏移,您必须实施一些规则,所以我建议使用pytz库,即使对于python 3也是如此。

例如,

>>> import datetime
>>> utc_now = datetime.datetime.utcnow()
>>> utc_now.isoformat()
'2019-05-21T02:30:09.422638'
>>> utc_now.tzinfo
(None)
Run Code Online (Sandbox Code Playgroud)

如果我将时区应用于此datetime对象,则时间不会更改(或将对<python 3.7ish发出ValueError)。

>>> mst_now = utc_now.astimezone(pytz.timezone('America/Denver'))
>>> mst_now.isoformat()
'2019-05-21T02:30:09.422638-06:00'
>>> utc_now.isoformat()
'2019-05-21T02:30:09.422638'
Run Code Online (Sandbox Code Playgroud)

但是,如果相反,我会

>>> import pytz
>>> utc_now = datetime.datetime.now(tz=pytz.timezone('UTC'))
>>> utc_now.tzinfo
<UTC>
Run Code Online (Sandbox Code Playgroud)

现在我们可以在所需的任何时区中创建正确转换的datetime对象

>>> mst_now = utc_now.astimezone(pytz.timezone('America/Denver'))
>>> mst_now.isoformat()
'2019-05-20T20:31:44.913939-06:00'
Run Code Online (Sandbox Code Playgroud)

啊哈!现在将其应用于日志记录模块。

带有时区的字符串表示的时间戳记

LogRecord created属性设置为从时间模块创建LogRecord的时间(由time.time()返回。这将返回一个时间戳(自epoch以来的秒数)。您可以对给定的时区进行自己的翻译,但是我还是建议通过覆盖转换器来pytz。

import datetime
import logging
import pytz

class Formatter(logging.Formatter):
    """override logging.Formatter to use an aware datetime object"""
    def converter(self, timestamp):
        dt = datetime.datetime.fromtimestamp(timestamp)
        tzinfo = pytz.timezone('America/Denver')
        return tzinfo.localize(dt)

    def formatTime(self, record, datefmt=None):
        dt = self.converter(record.created)
        if datefmt:
            s = dt.strftime(datefmt)
        else:
            try:
                s = dt.isoformat(timespec='milliseconds')
            except TypeError:
                s = dt.isoformat()
        return s
Run Code Online (Sandbox Code Playgroud)

Python 3.5、2.7

>>> logger = logging.root
>>> handler = logging.StreamHandler()
>>> handler.setFormatter(Formatter("%(asctime)s %(message)s"))
>>> logger.addHandler(handler)
>>> logger.setLevel(logging.DEBUG)
>>> logger.debug('test')
2019-05-20T22:25:10.758782-06:00 test
Run Code Online (Sandbox Code Playgroud)

Python 3.7

>>> logger = logging.root
>>> handler = logging.StreamHandler()
>>> handler.setFormatter(Formatter("%(asctime)s %(message)s"))
>>> logger.addHandler(handler)
>>> logger.setLevel(logging.DEBUG)
>>> logger.debug('test')
2019-05-20T22:29:21.678-06:00 test
Run Code Online (Sandbox Code Playgroud)

代替America/DenverAmerica/Anchorage对POSIX时区由pytz所限定

>>> next(_ for _ in pytz.common_timezones if 'Alaska' in _)
'US/Alaska'
Run Code Online (Sandbox Code Playgroud)

美国/阿拉斯加已弃用

>>> [_ for _ in pytz.all_timezones if 'Anchorage' in _]
['America/Anchorage']
Run Code Online (Sandbox Code Playgroud)

本地

如果您遇到了这个问题并找到了如何记录本地时区的答案,则可以使用tzlocalpip install tzlocal)代替

        tzinfo = pytz.timezone('America/Denver')
Run Code Online (Sandbox Code Playgroud)

        tzinfo = tzlocal.get_localzone()
Run Code Online (Sandbox Code Playgroud)

现在,它将在运行脚本的任何服务器上运行,并且服务器上带有时区。

不记录UTC时的警告

我应该添加,取决于应用程序,在本地时区登录可能会导致每年两次模糊性,跳过2 AM或1 AM重复,甚至其他。