Python logging: override log time

2019-05-05 02:05发布

Following Python's documentation, I'm trying to override logging.Formatter.converter in order to control the time logged.
As you can see below - the milliseconds were not overriden (they are the current time milliseconds).

How come? How can I control the milliseconds as well?

>>> 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条回答
看我几分像从前
2楼-- · 2019-05-05 02:49

Here's a better example that allows you to replace the time that was generated, as the accepted answer didn't really do that.

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)

To enable it:

logging.Formatter.converter=inSimulatedTime
查看更多
做自己的国王
3楼-- · 2019-05-05 02:51

override logging.Formatter.formatTime() instead with this:

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

If you need it for all loggers in this process, you can override the class function itself, but do this right after the first import logging statement your code encounters:

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
查看更多
乱世女痞
4楼-- · 2019-05-05 02:53

timetuple() doesn't use milliseconds, so that the ms information contained in the datetime object is lost once the method is called:

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

Note that this is not a limitation of this particular method, but rather of the time.struct_time type.

The bottom line is: if you need to override the timestamp, don't pass through a time.struct_time object. You could - for example - pass the timestamp already formatted as a string, rather than a fake time. Depending on your needs there might be better methods, of course!

查看更多
登录 后发表回答