Python日志记录模块记录时间戳包括微秒

时间:2015-07-09 21:10:38

标签: python logging

我正在使用python的日志记录模块,但需要时间戳包含微秒。似乎时间戳只能达到毫秒级的精确度。 这是我的测试代码

import logging

logging.basicConfig(format='%(asctime)s %(levelname)s {%(module)s} [%(funcName)s] %(message)s',

    datefmt='%Y-%m-%d,%H:%M:%S:%f', level=logging.INFO)

class log2_test():

    def test_class(self):

        logging.warning("Warning2 inside the class")

def get_started2():

    logging.info("Logged2 Here")

if __name__ == '__main__':
    get_started2()

这是我得到的输出 -

2015-07-09,16:36:37:f INFO {logger} [get_started2] Logged2 Here

不知何故,%f无法识别。 Python版本是2.7.6。

如何让时间戳包含微秒? 提前谢谢。

4 个答案:

答案 0 :(得分:9)

我认为strftime()不会直接支持%f。记录器确实提供毫秒作为单独的msecs attribute,因此您可以在现有时间戳之后自行添加它,如下所示:

logging.basicConfig(format='%(asctime)s.%(msecs)03d %(levelname)s {%(module)s} [%(funcName)s] %(message)s', datefmt='%Y-%m-%d,%H:%M:%S', level=logging.INFO)

这使用您的脚本为我提供了以下输出:

2015-07-10,09:21:16.841 INFO {test script} [get_started2] Logged2 Here

答案 1 :(得分:3)

我没有找到一种简单的方法来打印微秒,但%(created).6f可能是一个临时解决方案,这将是time.time()的结果,如1517080746.007748

没有找到删除不必要部分的方法,所以如果你真的需要微秒,但又不想更改你的代码, 一个简单的方法是

logging.basicConfig(level=logging.INFO,format="%(asctime)s.%(msecs)03d[%(levelname)-8s]:%(created).6f %(message)s", datefmt="%Y-%m-%d %H:%M:%S")

它会给你以下输出,

2018-01-28 04:19:06.807[INFO    ]:1517080746.807794 buy order issued
2018-01-28 04:19:07.007[INFO    ]:1517080747.007806 buy order issued
2018-01-28 04:19:07.207[INFO    ]:1517080747.207817 buy order issued
2018-01-28 04:19:07.407[INFO    ]:1517080747.407829 buy order issued
2018-01-28 04:19:07.607[INFO    ]:1517080747.607840 buy order issued

答案 2 :(得分:1)

我只是遇到了这个问题-它可以解决。它仅需要对某些日志记录基础架构进行一些改动。参见以下示例:

import logging
import time

try: # Python >= 3.7
    from time import time_ns
except: # Python <= 3.6
    from time import time as _time_
    time_ns = lambda: int(_time_() * 1e9)

class LogRecord_ns(logging.LogRecord):
    def __init__(self, *args, **kwargs):
        self.created_ns = time_ns() # Fetch precise timestamp
        super().__init__(*args, **kwargs)

class Formatter_ns(logging.Formatter):
    default_nsec_format = '%s,%09d'
    def formatTime(self, record, datefmt=None):
        if datefmt is not None: # Do not handle custom formats here ...
            return super().formatTime(record, datefmt) # ... leave to original implementation
        ct = self.converter(record.created_ns / 1e9)
        t = time.strftime(self.default_time_format, ct)
        s = self.default_nsec_format % (t, record.created_ns - (record.created_ns // 10**9) * 10**9)
        return s

logging.setLogRecordFactory(LogRecord_ns)

# +++++ DEMO +++++

log_formater = Formatter_ns('%(asctime)s (%(name)s) %(message)s')

logger = logging.getLogger('demo-log')
logger.setLevel(logging.DEBUG)

ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(log_formater)
logger.addHandler(ch)

logger.info('foo bar')

这将很高兴地显示:2019-04-10 14:08:28,819931368 (demo-log) foo bar

对此的关键是经过修改的logging.Formatter类,该类具有formatTime的自定义实现。为了安全起见,我还建议使用time.time_ns,它将在Python 3.7及更高版本中以毫微秒为单位返回整数。原始time.time返回以秒为单位的浮点数,因此显然存在精度问题。通过修改后的logging.LogRecord类可以将更精确的时间戳记入日志记录,该类只需在扩展构造函数方法中从created_ns中获取其time.time_ns字段即可。

答案 3 :(得分:0)

只需完成python 3.7的@Luo_Hongshuai答案:

format=%(asctime)s.%(msecs)06f
datefmt=%Y-%m-%d %H:%M:%S