如何在Python日志文件中格式化输出字典为整块内容?
问题:Python日志中字典内容的整块格式化输出需求
已配置可输出到流与文件的logging处理器,处理字典数据时希望将其格式化为整块内容输出到日志文件,而非单行分散显示。在编写字典专属自定义格式化器前,想了解是否有现成实现方案。
期望输出示例
2024-02-13 13:27:03,685 [DEBUG] root: shelf_name = 'some shelf', url = 'http://a_url', creation_date = '02/12/2024' 2024-02-13 13:34:55,889 [DEBUG] root:
当前实现代码
class Downloader: def __init__(self, shelf_data) -> None: shelf = ShelfData(shelf_data) [logging.debug(f"shelf['{key}']: {val}") for key, val in shelf.__dict__.items()]
当前日志文件输出
2024-02-13 16:29:18,024 [DEBUG] root: shelf['shelf_name']: test_shelf 2024-02-13 16:29:18,024 [DEBUG] root: shelf['url']: https://site/group/show/1865-scifi-and-fantasy-book-club 2024-02-13 16:29:18,024 [DEBUG] root: shelf['base_path']: C:\MyProjects\downloads 2024-02-13 16:29:18,024 [DEBUG] root: shelf['creation_date']: 02/12/2024 2024-02-13 16:29:18,039 [DEBUG] root: shelf['sort_order']: descend 2024-02-13 16:29:18,039 [DEBUG] root: shelf['books_per_page']: 100 2024-02-13 16:29:18,039 [DEBUG] root: shelf['download_dir']: None 2024-02-13 16:29:18,039 [DEBUG] root: shelf['book_count']: 37095 2024-02-13 16:29:18,039 [DEBUG] root: shelf['page_count']: 371
当前日志配置
import logging.config import os logging_config = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s' }, }, 'handlers': { 'default_handler': { 'class': 'logging.FileHandler', 'level': 'DEBUG', 'formatter': 'standard', 'filename': os.path.join('logs', f'{log_name}.log'), 'encoding': 'utf-8' }, 'stream_handler': { 'class': 'logging.StreamHandler', 'level': 'DEBUG', 'formatter': 'standard',} }, 'loggers': { '': { 'handlers': ['default_handler', 'stream_handler'], 'level': 'DEBUG', 'propagate': False } } } logging.config.dictConfig(logging_config)
现成实现方案
方案1:直接构造格式化后的多行消息
无需修改日志配置,在日志调用时手动把字典拼接成符合格式的多行字符串:
class Downloader: def __init__(self, shelf_data) -> None: shelf = ShelfData(shelf_data) lines = [] for key, val in shelf.__dict__.items(): # 给字符串值自动添加引号,非字符串保持原样 formatted_val = repr(val) if isinstance(val, str) else val lines.append(f"{key} = {formatted_val}") # 计算日志前缀长度,用缩进对齐后续行 prefix_length = len("2024-02-13 13:27:03,685 [DEBUG] root: ") indent = ' ' * prefix_length # 拼接成最终消息 if lines: message = ',\n'.join([lines[0]] + [indent + line for line in lines[1:]]) else: message = '' logging.debug(message)
方案2:用标准库pprint格式化字典
利用Python自带的pprint模块快速格式化字典,再调整缩进匹配日志前缀:
import pprint class Downloader: def __init__(self, shelf_data) -> None: shelf = ShelfData(shelf_data) # 用pprint生成格式化后的字符串 formatted_dict = pprint.pformat(shelf.__dict__, indent=4) # 替换换行符,添加对应缩进 prefix_length = len("2024-02-13 13:27:03,685 [DEBUG] root: ") indent = ' ' * prefix_length formatted_message = formatted_dict.replace('\n', '\n' + indent) logging.debug(formatted_message)
方案3:轻量自定义格式化器(全局生效)
如果希望所有字典类型的日志消息都自动格式化,可以自定义一个格式化器继承标准类:
import logging class DictFormatter(logging.Formatter): def format(self, record): # 检测消息是否为字典,是则格式化 if isinstance(record.msg, dict): prefix_length = len("2024-02-13 13:27:03,685 [DEBUG] root: ") indent = ' ' * prefix_length lines = [] for key, val in record.msg.items(): lines.append(f"{key} = {repr(val)}") record.msg = ',\n'.join([lines[0]] + [indent + line for line in lines[1:]]) if lines else '' return super().format(record)
修改日志配置,替换原有的格式化器:
logging_config = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'dict_formatter': { '()': DictFormatter, # 指定自定义格式化器类 'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s' }, }, 'handlers': { 'default_handler': { 'class': 'logging.FileHandler', 'level': 'DEBUG', 'formatter': 'dict_formatter', 'filename': os.path.join('logs', f'{log_name}.log'), 'encoding': 'utf-8' }, 'stream_handler': { 'class': 'logging.StreamHandler', 'level': 'DEBUG', 'formatter': 'dict_formatter',} }, 'loggers': { '': { 'handlers': ['default_handler', 'stream_handler'], 'level': 'DEBUG', 'propagate': False } } }
使用时直接传入字典即可:
class Downloader: def __init__(self, shelf_data) -> None: shelf = ShelfData(shelf_data) logging.debug(shelf.__dict__)
内容的提问来源于stack exchange,提问作者Meghan M.
相关产品推荐
相关产品推荐

