解决Python日志中datefmt导致时间戳固定的问题


解决Python日志中datefmt导致时间戳固定的问题

本文深入探讨了python `logging`模块中,当`datefmt`参数被错误地设置为一个预计算的固定时间戳字符串时,导致所有日志条目时间戳相同的问题。教程将解释`%(asctime)s`和`datefmt`的正确用法,并提供结合`%(msecs)03d`实现动态、高精度时间戳的解决方案,确保日志输出的时间戳能够实时更新并包含毫秒信息。

理解Python logging模块中的时间戳格式化

Python的logging模块是一个强大且灵活的日志记录框架。在配置日志格式时,我们经常会用到%(asctime)s占位符来显示日志记录的时间。%(asctime)s默认会以YYYY-MM-DD HH:MM:SS,mmm的格式输出时间,其中,mmm表示毫秒。然而,通过datefmt参数,我们可以自定义%(asctime)s的输出格式。

常见问题:datefmt导致时间戳固定

在配置logging时,一个常见的误区是将datefmt参数设置为一个通过datetime.now().isoformat()等方法预先计算好的时间戳字符串,而不是一个时间格式化字符串。例如:

import logging
from logging.config import dictConfig
from datetime import datetime
import sys

logging_config = dict(
    version=1,
    formatters={
        'verbose': {
            'format': ("%(asctime)s %(levelname)s "
                       "[%(name)s:%(lineno)s] %(message)s"),
            # 错误示例:datefmt被设置为一个固定时间戳字符串
            'datefmt': datetime.now().isoformat(sep='T', timespec='milliseconds')
        },
        'simple': {
            'format': '%(asctime)s %(levelname)-8s %(message)s',
            'datefmt': datetime.now().isoformat(sep='T', timespec='milliseconds')
        },
    },
    handlers={
        'console': {
            'class': 'logging.StreamHandler',
            'level': 'DEBUG',
            'formatter': 'verbose',
            'stream': sys.stdout,
        },
    },
    loggers={
        'logger': {
            'handlers': ['console'],
            'level': logging.DEBUG,
            'propagate': False
        },
    }
)

# 应用配置
dictConfig(logging_config)
logger = logging.getLogger('logger')

# 记录多条日志
logger.info("第一条日志")
logger.info("第二条日志")
logger.info("第三条日志")

当以上代码运行时,我们会发现所有日志条目都显示相同的%(asctime)s时间戳,且不包含毫秒信息,例如:

2025-01-04 03:18:18 INFO     [logger:38] 第一条日志
2025-01-04 03:18:18 INFO     [logger:39] 第二条日志
2025-01-04 03:18:18 INFO     [logger:40] 第三条日志

这是因为datefmt参数在日志配置字典被创建时,datetime.now().isoformat()就被立即评估并生成了一个固定的时间戳字符串(例如"2025-01-04T03:18:18.123")。此后,logging模块会将这个固定的字符串作为%(asctime)s的“格式”,而不是一个动态的时间格式化模式。结果就是,无论何时记录日志,%(asctime)s都将输出这个在配置加载时捕获的固定时间。

解决方案:正确使用format和datefmt

要实现动态且包含毫秒的时间戳,我们需要理解%(asctime)s和datefmt的真正作用:

  • %(asctime)s:这是一个特殊的占位符,它会在每次记录日志时动态捕获当前时间。
  • datefmt:它是一个字符串,用于指定如何格式化%(asctime)s所捕获的时间。它应该是一个标准的strftime()格式字符串,而不是一个实际的时间戳值。
  • %(msecs)03d:这是一个独立的占位符,用于显示当前时间的毫秒部分,并用零填充到三位数。

正确的做法是,在format字符串中明确包含%(msecs)03d来显示毫秒,并将datefmt设置为一个不包含毫秒的标准日期时间格式字符串。

悟空CRM v 0.5.5 悟空CRM v 0.5.5

悟空CRM是一种客户关系管理系统软件.它适应Windows、linux等多种操作系统,支持Apache、Nginx、IIs多种服务器软件。悟空CRM致力于为促进中小企业的发展做出更好更实用的软件,采用免费开源的方式,分享技术与经验。 悟空CRM 0.5.5 更新日志:2017-04-21 1.修复了几处安全隐患; 2.解决了任务.日程描述显示问题; 3.自定义字段添加时自动生成字段名

悟空CRM v 0.5.5 284 查看详情 悟空CRM v 0.5.5

以下是修正后的logging_config示例:

import logging
from logging.config import dictConfig
from datetime import datetime
import sys

logging_config = dict(
    version=1,
    formatters={
        'verbose': {
            # 修正1: 在format中添加 %(msecs)03d 来显示毫秒
            'format': ("%(asctime)s.%(msecs)03d %(levelname)s "
                       "[%(name)s:%(lineno)s] %(message)s"),
            # 修正2: datefmt 应为格式字符串,不包含毫秒,因为毫秒已由 %(msecs)03d 处理
            'datefmt': '%Y-%m-%dT%H:%M:%S'
        },
        'simple': {
            'format': '%(asctime)s.%(msecs)03d %(levelname)-8s %(message)s',
            'datefmt': '%Y-%m-%dT%H:%M:%S'
        },
    },
    handlers={
        # 示例中为了简化,仅保留console handler
        'console': {
            'class': 'logging.StreamHandler',
            'level': 'DEBUG',
            'formatter': 'verbose',
            'stream': sys.stdout,
        },
    },
    loggers={
        'logger': {
            'handlers': ['console'],
            'level': logging.DEBUG,
            'propagate': False
        },
    }
)

# 应用配置
dictConfig(logging_config)
logger = logging.getLogger('logger')

# 记录多条日志
logger.info("第一条日志")
logger.info("第二条日志")
logger.info("第三条日志")

通过上述修改,日志输出将显示动态且包含毫秒的时间戳:

2025-01-04T03:30:11.595 INFO     [logger:38] 第一条日志
2025-01-04T03:30:11.598 INFO     [logger:39] 第二条日志
2025-01-04T03:30:11.603 INFO     [logger:40] 第三条日志

这里的关键在于:

  1. datefmt: '%Y-%m-%dT%H:%M:%S' 告诉%(asctime)s将其捕获的时间格式化为年-月-日T时:分:秒的形式。
  2. %(msecs)03d 在format字符串中被独立地解析和替换为当前的毫秒数。 这样,%(asctime)s负责提供实时的时间(不含毫秒),datefmt负责格式化这个时间,而%(msecs)03d则负责提供实时的毫秒部分,三者结合实现了我们期望的动态高精度时间戳。

注意事项

  • datefmt的默认行为:如果datefmt未指定,%(asctime)s会使用默认的YYYY-MM-DD HH:MM:SS,mmm格式。在这种情况下,通常不需要额外添加%(msecs)03d,除非你想自定义日期时间部分的格式。
  • datetime.now()的执行时机:任何在logging_config字典定义时调用的函数(如datetime.now())都会在字典创建时立即执行一次,其结果会成为字典的一部分。因此,datefmt必须是一个格式字符串,而不是一个函数调用的结果。
  • 文件处理器命名中的时间戳:如果需要在日志文件名中包含动态时间戳,如原问题中的filename: '/home/abc/efg/logs/logtest_'+datetime.now().strftime("%Y%m%d-%H%M%S")+'.log',这种用法是正确的。因为文件名只需要在文件创建时确定一次,而不是在每次日志记录时都动态更新。

总结

在Python logging模块中,实现动态且包含毫秒的时间戳,核心在于正确区分format字符串中占位符的作用以及datefmt参数的预期值。datefmt应始终是一个strftime()兼容的格式字符串,用于指导%(asctime)s如何格式化其捕获的时间。要包含毫秒,最可靠的方法是在format字符串中显式使用%(msecs)03d占位符,并相应地调整datefmt以避免重复或冲突的格式化。遵循这些原则,可以确保日志系统提供准确、实时的事件时间记录。

以上就是解决Python日志中datefmt导致时间戳固定的问题的详细内容,更多请关注其它相关文章!


# 处理器  # python  # 第一条  # 而不  # 是一个  # gate  # yy  # 常见问题  # stream  # 亦庄网站建设优化推广  # 外贸网站优化推广技巧  # 优化糖贴网站  # seo搜索资料的技巧  # 新颖的营销推广策略  # 咸宁企业营销型网站建设  # 新吴区网站优化推广  # 鲤城网站推广营销公司  # 北京多媒体教室网站建设  # 资讯建设网站  # 不包含  # 浮点  # 是在  # 自定义  # 第三条  # 第二条  # 设置为 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: Golang如何初始化module项目_Golang module init使用说明  网站体验不好=浪费钱:如何提升-用户体验效果差  Win10如何彻底关闭OneDrive Win10禁用云同步功能【纯净】  iSpring三分屏制作教程  猫眼电影app如何参与官方的抽奖活动_猫眼电影官方抽奖参与方法  CSS绝对定位与溢出控制:实现背景元素局部显示不触发滚动条  百度竞价WAP显示PC链接问题  Golang如何操作指针参数_Go pointer参数传递规则  优化 WooCommerce 产品价格显示与自定义短代码集成  如何用mysql实现客户反馈管理_mysql客户反馈数据库方法  智学网app怎么登录忘记密码_智学网app忘记密码找回与重新登录操作方法  C++ optional用法详解_C++17处理可能为空的返回值  J*aScript模块加载器_RequireJS原理分析  重返未来:1999卡戎全方位攻略  GBA模拟器手柄按键设置  《合金装备4》有望推出重制版!制作人发话了  动漫岛在线动漫网 动漫岛动漫在线观看官方入口  微信网页版在线登录 微信网页版在线使用入口  Sublime怎么快速复制文件路径_Sublime右键菜单增强技巧  第五人格PC版怎么避免被封号_第五人格PC版防封号注意事项  淘口令快速解析技巧  百度网盘如何设置上传限额  一点万象签到领积分指南  汽水音乐官网网页版入口 汽水音乐官网网页版在线入口  搜狗浏览器如何查找页面中的文字 搜狗浏览器Ctrl+F页面搜索功能  在PySimpleGUI中实现键盘按键绑定按钮事件  steam缓存文件在哪儿_steam缓存文件的路径查找方法与结构说明  firefox火狐浏览器最新官网主页_ firefox火狐浏览器平台入口直达官方链接  豆包AI怎样为教育场景定制答疑逻辑_为教育场景定制豆包AI答疑逻辑方案【方案】  虫虫漫画绿色安全入口_虫虫漫画绿色安全入口安全看漫画  智学网成绩单查询系统网_智学网学生平台登录  Go语言中方法接收器的选择:值类型还是指针类型?  J*aScript二进制处理_ArrayBuffer与Blob  《浙里办》电子发票开具方法  PHP中实现JSON数据数组分页的教程  Dash应用多值文本输入处理与类型转换教程  《下一站江湖2》大雪山加入方法  《爱笔思画x》涂色教程  解决Flex容器横向滚动内容截断与偏移问题  小红书网页版怎么进 小红书网页版通用入口  《U校园》学生登录入口2025  12306夜间购票失败? | 查看官方公布的暂停服务公告与应对方案  J*aScript 数值去小数位处理:多种方法与实践  在Django单元测试中优雅处理信号:基于环境的条件执行策略  Go语言反射机制下访问嵌入结构体中的被遮蔽方法  如何外贸网站设计-能留住客户提升用户体验!  如何在mysql中比较InnoDB和MyISAM区别  《糖豆》添加舞曲方法  Selenium自动化:利用键盘模拟解决复杂日期输入框输入问题  win11自带录屏文件保存在哪里 Win11 Game Bar录制视频默认路径【分享】 

 2025-11-27

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.