【问题标题】:Python Logging Module logging timestamp to include microsecondPython Logging Module 记录时间戳以包括微秒
【发布时间】:2015-09-28 11:12:18
【问题描述】:

我正在使用 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。

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

【问题讨论】:

  • @Vignesh Kalai "timestamp" 是一个词
  • 你应该尝试谷歌搜索'logging datefmt',你会看到这已经得到了广泛的回答:stackoverflow.com/questions/6290739/…
  • @jonnybazookatone 提供的链接给了我解决方案。谢谢
  • @HanGu 你能把你使用的解决方案贴在这里并标记为答案吗?我正在尝试使用格式化程序获得微秒,但无法获得所有 6 位数字的真正微秒。现在我正在使用 6 位数形式的毫秒,如下所示:logging.Formatter('%(asctime)s.%(msecs)06d', datefmt='%Y-%m-%d %H:%M:%S') 如果其他人可以发布获得真正微秒的答案,那么这将是很棒的,因为这个问题出现在谷歌搜索这个主题上。

标签: python logging


【解决方案1】:

根据the documentationstrftime() 不支持%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

【讨论】:

  • 我实际上需要精确到微秒。
  • 您可能需要研究子类并添加您自己的功能。作为 Python,我不确定这些数字有多精确。我似乎记得这样做是为了修改格式。不过,它现在似乎更加灵活了。
  • 谢谢马丁。我从上面 cmets 中某人提供的链接中找到了答案。事实上,它确实涉及对 logging.formatter 进行子类化,并修改格式。
【解决方案2】:

我刚刚遇到了这个问题 - 它可以解决。它只需要对一些日志基础设施进行一些黑客攻击。见下例:

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 类可以在日志记录中获取更精确的时间戳,该类只是在其扩展构造方法中从time.time_ns 中获取其created_ns 字段。

【讨论】:

    【解决方案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
    

    【讨论】:

      【解决方案4】:

      刚刚完成@Luo_Hongshua 对 python 3.7 的回答:

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

      【讨论】:

      • 这给了我 260.363817(即 260 点 363817 毫秒),有什么方法可以删除 .
      • 我需要某个固定参考的时间戳(以秒为单位)。自程序启动以来的秒数会很好,但过去的任何固定点都可以,
      【解决方案5】:

      我有同样的问题:使用 logging.Formatter 需要以微秒为单位的时间戳,精确到 6 位数。比如:2021-11-02 15:21:12.891531

      在仔细阅读答案并查看此处提到的其他 SO 链接后,我找不到以这种格式获取时间戳的方法。有谁知道如何获取2021-11-02 15:21:12.891531 格式的时间戳?

      我尝试过关注,代码中每一行旁边的注释就是该行打印为日期的内容。

        1 #!/bla/bla/bla/bin/python
        2
        3 import logging
        4
        5 logger = logging.getLogger(__name__)
        6 l_level = 'INFO'
        7 l_level = eval("logging." + l_level.upper())
        8 logger.setLevel(l_level)
        9
       10 handler = logging.StreamHandler()
       11 handler.setLevel(l_level)
       12
       13 #formatter = logging.Formatter('%(asctime)s|%(message)s', datefmt="%Y-%m-%d %H:%M:%S.%s") # 2021-11-02 15:12:59.1635880379
       14 #formatter = logging.Formatter('%(asctime)s.%(msecs)06d|%(message)s', datefmt="%Y-%m-%d %H:%M:%S") # 2021-11-02 15:11:50.000952
       15 #formatter = logging.Formatter('%(asctime)s.%(msecs)03d|%(message)s', datefmt="%Y-%m-%d %H:%M:%S") # 2021-11-02 15:12:10.633
       16 formatter = logging.Formatter('%(asctime)s.%(msecs)06f', datefmt="%Y-%m-%d %H:%M:%S") # 2021-11-02 15:18:04.274.372101
       17 handler.setFormatter(formatter)
       18 logger.addHandler(handler)
       19
       20 logger.info("")
      

      如果我发现新选项,我会在这里添加更多方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-06
        • 2016-11-22
        • 2013-06-22
        • 2014-09-20
        • 2015-04-12
        • 1970-01-01
        • 2014-04-07
        • 1970-01-01
        相关资源
        最近更新 更多