由于我的应用程序的特定要求,我需要为单个日志记录条目添加相同的时间戳,但每个时间戳具有不同的格式。这两个时间戳彼此不相邻,因此其他日志记录字段位于它们之间。由于datefmt
作为format
中formatter
的第二个参数传递,我还没有弄清楚如何为单个日志记录条目提供两种不同的日期格式。< / p>
我要问的唯一问题是,如果可以使用Python而不使用自定义格式化程序或过滤器。
答案 0 :(得分:2)
由于源代码的编写方式,这在stdlib logging
中是不可能的。 formatter类将使用asctime
方法在每个LogRecord
实例上设置formatTime
。正如您在日志记录模块中看到的代码here,相关字段%(asctime)
实际上是字符串属性,而不是datetime
实例。这意味着它不能接受除了简单的字符串操作之外的自定义格式,例如填充和对齐。
我同意你的看法,这是stdlib logging
模块的一个缺点,并敦促你考虑一个更强大的日志框架,例如structlog。
您的问题的其他读者可能不会反对在stdlib日志记录中使用Formatter
子类。对于他们,我建议定义一个格式化程序,它使用datetime
实例上的LogRecord
实例,并结合大括号样式格式化程序模板字符串。这允许不受限制地使用具有多种strftime格式的asctime
字段。
设置比使用Filter
或LoggingAdapter
更简单,它只是formatTime
方法的一行覆盖:
import logging
from datetime import datetime
class MyFormatter(logging.Formatter):
def formatTime(self, record, datefmt=None):
return datetime.fromtimestamp(record.created)
fmt = '{asctime:%Y-%m-%d %H:%M:%S} - {levelname} - {asctime:%a %b %d %Y} - {message}'
logger = logging.getLogger()
handler = logging.StreamHandler()
handler.setFormatter(MyFormatter(fmt=fmt, style='{'))
logger.addHandler(handler)
logger.warning('the message')
注意:如果您需要的格式之一只是一个时间戳(自纪元以来的秒数),那么您就不需要自定义Formatter&#34;体操&#34;完全 - 您可以将created
字段(接受浮动格式自定义)与asctime
字段结合使用。
答案 1 :(得分:1)
具有原始时间戳和人类可读日期的非常基本的示例:
import logging
import sys
from datetime import datetime
class ContextFilter(logging.Filter):
"""
This is a filter which injects contextual information into the log.
"""
@staticmethod
def some_format(timestamp):
return datetime.fromtimestamp(
timestamp
).strftime('%Y-%m-%d %H:%M:%S')
def filter(self, record):
record.format1 = record.created
record.format2 = self.some_format(record.created)
return True
formatter = logging.Formatter('%(format1)s - %(format2)s - %(name)s - %(levelname)s: %(message)s')
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(formatter)
handler.setLevel(logging.DEBUG)
logger = logging.Logger('test')
logger.addHandler(handler)
f = ContextFilter()
logger.addFilter(f)
logger.info('test')
输出:
1525883052.4808118 - 2018-05-09 19:24:12 - test - INFO: test