[英]How to change the format of logged messages temporarily, in Python?
在 Python 中(通过 logging 模块)临时更改日志消息格式的最简单方法是什么?
目标是拥有一些标准的消息格式,同时能够临时添加有关正在读取的某些文件的信息(如其名称); 当不再读取文件时,消息格式应恢复为默认值。 生成消息的程序不知道正在读取哪个文件,因此如果其消息自动包含相关文件名(错误消息将是:“读取文件时出错 ***:……”而不是“错误: …”)。
这是一个简单的解决方案,可以从Vinay Sajip自己的HOWTO推导出来; 它基本上使用setFormatter()
更新日志格式化程序:
import logging
logger = logging.getLogger() # Logger
logger_handler = logging.StreamHandler() # Handler for the logger
logger.addHandler(logger_handler)
# First, generic formatter:
logger_handler.setFormatter(logging.Formatter('%(message)s'))
logger.error('error message') # Test
# New formatter for the handler:
logger_handler.setFormatter(logging.Formatter('PROCESSING FILE xxx - %(message)s'))
logger.error('error message') # Test
这正确地产生:
error message
PROCESSING FILE xxx - error message
(其中xxx
可以动态设置为正在处理的文件,如问题中所要求)。
有几种方法。 除了已经记录的那些(记录调用的extra
参数, LoggerAdapter
, Filter
),另一种方法是指定自定义格式类,您可以随时了解正在处理的文件的实例。 例如:
class FileProcessingFormatter(logging.Formatter):
def __init__(self, fmt, datefmt=None, current_file=None):
super(FileProcessingFormatter, self).__init__(fmt, datefmt)
self.orig_fmt = fmt
self.current_file = current_file
def format(self, record):
if self.current_file is None:
self._fmt = self.orig_fmt.replace('__FILE_PLACEHOLDER__', '')
else:
self._fmt = self.orig_fmt.replace('__FILE_PLACEHOLDER__',
' while processing %r' % self.current_file)
return super(FileProcessingFormatter, self).format(record)
实例化格式化程序...
f = FileProcessingFormatter('%(levelname)s__FILE_PLACEHOLDER__ %(message)s')
for h in relevant_handlers:
h.setFormatter(f)
处理文件...
f.current_file = fn
process_file(fn)
f.current_file = None
这是非常简单的 - 例如,如果文件处理由不同的线程并发完成,则不适用于线程环境。
更新:虽然可以通过logging.getLogger().handlers
访问根记录器的处理logging.getLogger().handlers
,但这是一个可能会更改的实现细节。 由于您的要求不是那么基本,您也许可以使用dictConfig()
来配置您的日志记录(可通过logutils项目获取旧版本的 Python)。
我不推荐这个; 但是你可以说假设第一个根处理程序被搞砸了并直接修改它
import logging
ROOT_LOGGER = logging.getLogger()
ROOT_LOGGER.handlers[0].setFormatter(logging.Formatter(
'%(asctime)s:%(levelname)s:%(name)s:%(message)s\n'
))
如果您在任何具有托管日志记录的系统中; 这可能会射你的脚; 最好能够确定对要修改和修改的处理程序的确切引用;
但没有人关心它是否正常工作?/s
正如@Vinay Sajip 在更新中提到的那样,使用dictConfig()似乎是要走的路。 这是 Python 3.8 中的一个有效实现。
import logging
from logging.config import dictConfig
FI_PATH_CONSUMERS_LOG = "/project/test_log.log"
LOG_FORMAT = "%(asctime)s %(levelname)-8s [%(name)s] %(message)s"
LOG_LEVEL = "INFO"
LOG_DATEFMT = "%Y-%m-%d %H:%M:%S"
logging.basicConfig(
filename=FI_PATH_CONSUMERS_LOG,
format=LOG_FORMAT,
level=getattr(logging, LOG_LEVEL),
datefmt=LOG_DATEFMT,
)
logger = logging.getLogger() # root logger
logger_2 = logging.getLogger("2") # child logger with name "2"
msg_test = "TEST TEST TEST"
def create_new_format(add_stuff: str=""):
alt_new_formats = {
"event_format": {
"format": LOG_FORMAT + add_stuff,
"datefmt": LOG_DATEFMT,
},
}
changed_setting = {
"version": 1,
"formatters": alt_new_formats,
"handlers": {
"to_file": {
"class": "logging.FileHandler",
"filename": FI_PATH_CONSUMERS_LOG,
"formatter": "event_format",
"level": LOG_LEVEL,
},
},
"loggers": {
"": {
"handlers": ["to_file"],
},
},
"disable_existing_loggers": False,
}
return changed_setting
logger.info(msg_test)
logger_2.info(msg_test)
dictConfig(create_new_format("...adding some stuff"))
logger.info(msg_test)
logger_2.info(msg_test)
dictConfig(create_new_format())
logger.info(msg_test)
logger_2.info(msg_test)
这会给你:
2021-07-20 23:02:11 INFO [root] TEST TEST TEST
2021-07-20 23:02:11 INFO [2] TEST TEST TEST
2021-07-20 23:02:11 INFO [root] TEST TEST TEST...adding some stuff
2021-07-20 23:02:11 INFO [2] TEST TEST TEST...adding some stuff
2021-07-20 23:02:11 INFO [root] TEST TEST TEST
2021-07-20 23:02:11 INFO [2] TEST TEST TEST
如果你想动态改变日志的格式。 它可以像这样制作。
logger = logging.getLogger()
# Change format of handler for the logger
logger.handlers[0].setFormatter(logging.Formatter('%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s'))
# Print log
logging.info(log)
# return other format
logger.handlers[0].setFormatter(logging.Formatter('%(message)s'))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.