Python日志:重写日志时间

4 投票
3 回答
3078 浏览
提问于 2025-04-17 07:40

根据Python的文档,我正在尝试重写logging.Formatter.converter,以便控制记录的时间。
如你所见 - 毫秒部分没有被重写(它们显示的是当前时间的毫秒)。

这是为什么呢?我该如何控制毫秒部分呢?

>>> import logging, datetime
>>> formatter = logging.Formatter('%(asctime)s:%(message)s')
>>> handler = logging.StreamHandler()
>>> handler.setFormatter(formatter)
>>> def sim_time(t):
...     return datetime.datetime(2000,1,2,3,4,5,678).timetuple()
...
>>> formatter.converter = sim_time
>>> log = logging.getLogger('test')
>>> log.addHandler(handler)
>>> log.info('hi')
2000-01-02 03:04:05,898:hi
>>> log.info('hi')
2000-01-02 03:04:05,914:hi
>>> log.info('hi')
2000-01-02 03:04:05,434:hi

3 个回答

0

这里有一个更好的例子,它可以让你替换生成的时间,因为之前的答案并没有真正做到这一点。

def inSimulatedTime(self,secs=None):
    global myTimeKeeper
    try:
       ts=myTimeKeeper.getCurrentTimeLocal() # returns a datetime.datetime object
       return ts.timetuple()
except Exception as e:
    #sometimes my timekeeper hasn't been initialized yet.
    return time.localtime(secs)

要启用这个功能:

logging.Formatter.converter=inSimulatedTime
1

timetuple() 这个方法不支持毫秒,所以当你调用这个方法时,datetime对象中的毫秒信息就会丢失。

>>> d
datetime.datetime(2000, 1, 2, 3, 4, 5, 678)
>>> d.timetuple()
time.struct_time(tm_year=2000, tm_mon=1, tm_mday=2, tm_hour=3, tm_min=4, tm_sec=5, tm_wday=6, tm_yday=2, tm_isdst=-1)

需要注意的是,这并不是这个方法的局限性,而是 time.struct_time 类型 的限制。

总的来说,如果你需要覆盖时间戳,就不要传递 time.struct_time 对象。你可以直接传递已经格式化好的字符串时间,而不是一个伪造的时间。根据你的需求,可能还有更好的方法可以选择!

3

用下面的方式来替代 logging.Formatter.formatTime()

def sim_time(record, datefmt=None):
    return datetime.datetime(2000,1,2,3,4,5,678).strftime('%Y-%m-%d %H:%M:%S,%f')[:-3]

formatter.formatTime = sim_time

如果你想让这个设置在这个程序中的所有日志记录器都生效,你可以直接修改这个类的函数,但要确保在代码中第一次出现 import logging 语句之后立刻进行修改:

def sim_time(self, record, datefmt=None):
    return datetime.datetime(2000,1,2,3,4,5,678).strftime('%Y-%m-%d %H:%M:%S,%f')[:-3]

import logging
logging.Formatter.formatTime = sim_time

撰写回答