新闻中心
解决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设置为一个不包含毫秒的标准日期时间格式字符串。
Motiff妙多
Motiff妙多是一款AI驱动的界面设计工具,定位为“AI时代设计工具”
334
查看详情
以下是修正后的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] 第三条日志
这里的关键在于:
- datefmt: '%Y-%m-%dT%H:%M:%S' 告诉%(asctime)s将其捕获的时间格式化为年-月-日T时:分:秒的形式。
- %(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论坛领域博主
# seo优化中白帽seo和黑帽seo的区别
# 益阳网站建设加推广费用
# 度假酒店营销推广活动
# seo兵书 pdf
# 休闲网站推广方案
# seo新手快速入门推广
# 网站建设公司固定ip
# 这是一个
# 会在
# 不包含
# 是在
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
J*aScript:在map操作中高效处理空数组
Python字典中优雅地迭代剩余元素的方法
Node.js CSV 数据处理:基于字段值条件过滤整条记录的策略
蛙漫安全无毒 官方认证的绿色入口
Django表单验证失败时保留用户输入数据的最佳实践
印象笔记怎样用批量导出备知识库_印象笔记用批量导出备知识库【备份方法】
深入理解J*a合成构造器:何时以及为何阻止其生成
葱吃多了会怎样 葱吃多了会伤胃吗
微信网页版官方快速登录入口 微信网页版网页版账号直达
C++如何操作大型数据集_使用C++流式处理(Streaming)技术避免一次性加载大文件
C#中解析不规范的HTML为XML 常见的坑与解决办法
Python类型检查:优化关联可选属性的Mypy推断策略
C++如何实现一个智能指针_手动实现C++ shared_ptr的引用计数功能
css卡片内容溢出如何处理_使用overflow隐藏或scroll显示内容
搜狗浏览器如何使用密码生成器创建强密码 搜狗浏览器内置密码安全工具
sublime怎么覆盖插件的默认快捷键_sublime快捷键优先级与设置
三星GalaxyZFold5怎样在相册制作折叠屏分镜_iPhone三星GalaxyZFold5相册制作折叠屏分镜【创意编辑】
QQ网页版官方账号入口 QQ网页版网页版登录指南
谷歌浏览器浏览体验优化_谷歌浏览器新版直连永久可用提示
小米Civi 4录制视频过暗_小米Civi 4亮度优化
钉钉视频会议画面卡顿如何解决 钉钉会议画面优化方法
如何在离线环境中使用Composer_Composer离线安装依赖包的技巧与策略
Python多版本共存与虚拟环境管理深度指南
如何使用CaptainHook和Composer管理Git钩子_在提交前自动运行代码检查的Composer配置
Go语言中Map存储的结构体如何调用指针方法:深入解析与实践
《北京人工智能产业白皮书(2025)》发布:全年核心产值预计突破 4500 亿元
在J*aScript中复现SciPy的B样条拟合与求值:关键考量
想当下一个《2077》?《心之眼》Steam评价升至"多半好评"
python3时间如何用calendar输出?
深入理解Google Cloud Datastore查询:祖先路径与数据一致性
mysql通配符支持数字匹配吗_mysql通配符能否用于数字匹配的解析
学习通网页版快速入口 学习通官网网页版直接打开
PHP中高效并行检查多链接状态的教程
React Router v6 教程:构建认证保护的私有路由与重定向策略
押井守高度称赞《辐射4》:玩了八年都停不下来!
AO3官网镜像链接 Archive of Our Own同人文在线浏览
为什么我的微信朋友圈看不到别人的更新_微信朋友圈更新显示异常解决方法
J*aScript中高效管理与清空动态列表:避免循环陷阱
J*a如何使用AtomicInteger控制计数_J*a无锁计数器性能分析
铁路12306改签能改到更早的车次吗_铁路12306改签提前车次规则
Win10文件资源管理器“此电脑”分组怎么关 Win10恢复经典视图【技巧】
使用 Pandas 高效处理 .dat 文件:字符清理与数据计算
德邦快递查询平台 德邦快递物流信息查询入口
c++如何使用Catch2编写单元测试_c++简洁易用的BDD风格测试框架
Go语言HTML解析:利用Goquery精准获取指定元素内容
Typer应用中动态命令行参数的解析与处理
优化 Jest 模拟:强制未实现函数抛出错误以提升测试效率
ACG动漫视频网入口 ACG动漫*免费正版观看地址
在Go开发中优雅管理ListenAndServe进程:GoSublime集成方案
Odoo 16:在表单视图中基于当前记录动态修改Tree视图属性


2025-11-27
浏览次数:次
返回列表