Databricks中配置双输出日志记录器的最佳实践及问题解决
在Databricks中配置双格式日志记录器
你的核心需求是让日志记录器同时实现两个效果:控制台仅输出纯消息(和print()一致),日志文件输出包含时间戳、级别等的详细内容。现有代码的问题在于流处理器(StreamHandler)和文件处理器使用了相同的格式化器,导致控制台也输出了详细信息。以下是修正后的完整实现:
修正后的代码
import logging from datetime import datetime import sys def get_current_date(): now = datetime.now() # 按需求生成大写的DDMMMYYYY格式日期(如12SEP2024) formatted_date = now.strftime("%d%b%Y").upper() return formatted_date def setup_custom_logger(notebook_name): # 生成带Notebook名称和日期的日志文件名,使用DBFS路径方便Databricks访问 formatted_date = get_current_date() log_file = f'/dbfs/{notebook_name}_{formatted_date}.log' # 初始化logger,设置最低日志级别 logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) # 清除已有处理器,避免重复调用函数时日志重复输出 if logger.hasHandlers(): logger.handlers.clear() # 文件处理器:输出详细格式到日志文件 file_handler = logging.FileHandler(log_file) file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') file_handler.setFormatter(file_formatter) # 流处理器(控制台):仅输出消息内容,模拟print行为 stream_handler = logging.StreamHandler(sys.stdout) stream_formatter = logging.Formatter('%(message)s') stream_handler.setFormatter(stream_formatter) # 将处理器添加到logger logger.addHandler(file_handler) logger.addHandler(stream_handler) return logger # 使用示例 if __name__ == "__main__": # 替换为你的Notebook名称 logger = setup_custom_logger("sales_analysis_notebook") logger.info('数据加载完成') logger.warning('检测到缺失值') logger.error('数据库连接失败')
关键改动说明
- 分离格式化器:给文件处理器和流处理器分别设置不同的格式化规则,流处理器仅保留
%(message)s,确保控制台输出和print()完全一致。 - 修复变量错误:原代码中直接使用未定义的
formatted_date变量会触发NameError,现在在初始化函数中正确调用get_current_date()生成日期。 - 避免重复日志:添加了处理器清除逻辑,防止多次调用初始化函数时重复添加处理器,导致同一条日志被多次打印。
- 适配Databricks路径:日志文件路径使用
/dbfs/前缀,确保日志文件写入DBFS分布式存储,后续可通过Databricks UI或命令行直接查看。
效果验证
- 控制台输出:
数据加载完成 检测到缺失值 数据库连接失败 - 日志文件(
sales_analysis_notebook_12SEP2024.log)内容:2024-09-12 14:35:22,187 - __main__ - INFO - 数据加载完成 2024-09-12 14:35:25,421 - __main__ - WARNING - 检测到缺失值 2024-09-12 14:35:28,763 - __main__ - ERROR - 数据库连接失败
内容的提问来源于stack exchange,提问作者csp
相关产品推荐
相关产品推荐

