电力负荷预测案例之日志功能介绍
1 课程概览
本课介绍电力负荷预测案例的日志工具类。包括日志级别、日志工具类初始化、日志使用方法等。强调日志在实际开发中的重要性。
2 核心概念与定义
- 日志级别:DEBUG、INFO、WARNING、ERROR、CRITICAL。
- 日志工具类:记录项目进展和错误信息。
- root_path:父目录,日志存放路径。
- log_name:日志名称。
- get_log:获取日志对象的方法。
3 算法与模型详解
3.1 日志级别
日志级别(从低到高):
| 级别 | 说明 | 示例 |
|---|---|---|
| DEBUG | 调试信息 | 调试代码 |
| INFO | 普通信息 | 项目进展 |
| WARNING | 警告信息 | 代码警告 |
| ERROR | 错误信息 | 报错 |
| CRITICAL | 严重错误 | 系统崩溃 |
特点:
- 越往上越严重
- 设置级别后,低于该级别的日志不打印
- 可以统一管理异常信息
3.2 日志级别设置
示例:
- 设置级别为DEBUG:所有日志都打印
- 设置级别为INFO:DEBUG不打印,其他都打印
- 设置级别为WARNING:只打印WARNING及以上
作用:
- 统一管理异常信息
- 避免使用print
- 注释和清理代码
3.3 日志工具类初始化
文件:utils/log.py
导包:
import logging
import os
初始化参数:
root_path:父目录(日志存放路径)log_name:日志名level:默认日志级别- 时间格式
3.4 get_log方法
功能:获取日志对象
实现:
def get_log(root_path, log_name):
# 组合路径
log_path = os.path.join(root_path, log_name + '.log')
# 类型转换
# 返回日志对象
return logger
说明:
- 自动组合root_path和log_name
- 自动添加.log后缀
- 只需写日志名,其他不用管
3.5 日志使用方法
使用步骤:
- 创建日志对象
- 设置父目录(一般用
./) - 设置日志名
- 自动创建log目录
父目录说明:
./:当前目录上一级(与utils平级)- 自动创建log目录
- 不要写
./log/(会变成log/log/)
3.6 测试代码
测试代码位置:
- 不能直接在模块中写测试代码
- 要写到
if __name__ == '__main__':中 - 避免导包时执行
4 代码示例
import os
import logging
import numpy as np
import pandas as pd
# 1. 日志工具类
print("=== 1. 日志工具类 ===")
class LogUtils:
"""日志工具类"""
def __init__(self, root_path='./', log_name='project', level=logging.INFO):
"""
初始化日志
Args:
root_path: 父目录(日志存放路径)
log_name: 日志名
level: 日志级别
"""
self.logger = logging.getLogger(log_name)
self.logger.setLevel(level)
# 避免重复添加handler
if not self.logger.handlers:
# 组合路径
log_dir = os.path.join(root_path, 'log')
os.makedirs(log_dir, exist_ok=True)
log_file = os.path.join(log_dir, f'{log_name}.log')
# 创建文件handler
file_handler = logging.FileHandler(log_file, encoding='utf-8')
file_handler.setLevel(level)
# 创建控制台handler
console_handler = logging.StreamHandler()
console_handler.setLevel(level)
# 创建格式器
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
# 添加handler
self.logger.addHandler(file_handler)
self.logger.addHandler(console_handler)
def get_log(self):
"""获取日志对象"""
return self.logger
# 2. 日志级别说明
print("\n=== 2. 日志级别说明 ===")
def show_log_levels():
"""显示日志级别"""
print("""
日志级别(从低到高):
1. DEBUG - 调试信息
2. INFO - 普通信息
3. WARNING - 警告信息
4. ERROR - 错误信息
5. CRITICAL - 严重错误
特点:
- 越往上越严重
- 设置级别后,低于该级别的日志不打印
- 可以统一管理异常信息
""")
show_log_levels()
# 3. 测试日志工具
print("\n=== 3. 测试日志工具 ===")
def test_log_utils():
"""测试日志工具"""
# 创建日志对象
log_utils = LogUtils(root_path='./', log_name='power_load', level=logging.DEBUG)
logger = log_utils.get_log()
# 测试各级别日志
logger.debug("这是DEBUG级别的日志")
logger.info("这是INFO级别的日志")
logger.warning("这是WARNING级别的日志")
logger.error("这是ERROR级别的日志")
logger.critical("这是CRITICAL级别的日志")
print("日志测试完成,查看log/power_load.log文件")
test_log_utils()
# 4. 日志级别过滤
print("\n=== 4. 日志级别过滤 ===")
def test_log_level_filter():
"""测试日志级别过滤"""
print("--- 设置级别为INFO ---")
log_utils_info = LogUtils(root_path='./', log_name='test_info', level=logging.INFO)
logger_info = log_utils_info.get_log()
logger_info.debug("DEBUG日志(不打印)")
logger_info.info("INFO日志(打印)")
logger_info.warning("WARNING日志(打印)")
print("\n--- 设置级别为WARNING ---")
log_utils_warning = LogUtils(root_path='./', log_name='test_warning', level=logging.WARNING)
logger_warning = log_utils_warning.get_log()
logger_warning.debug("DEBUG日志(不打印)")
logger_warning.info("INFO日志(不打印)")
logger_warning.warning("WARNING日志(打印)")
test_log_level_filter()
# 5. 实际应用示例
print("\n=== 5. 实际应用示例 ===")
def practical_application():
"""实际应用示例"""
# 创建日志对象
log_utils = LogUtils(root_path='./', log_name='power_load_prediction')
logger = log_utils.get_log()
try:
logger.info("项目启动")
logger.info("开始加载数据")
# 模拟加载数据
data = pd.DataFrame({
'time': pd.date_range('2024-01-01', periods=24, freq='h'),
'power_load': np.random.randint(500, 1200, 24)
})
logger.info(f"数据加载完成,形状: {data.shape}")
logger.info("开始特征工程")
# 模拟特征工程
data['hour'] = data['time'].dt.hour
logger.info("特征工程完成")
logger.info("开始模型训练")
# 模拟训练
logger.info("模型训练完成")
logger.info("项目完成")
except Exception as e:
logger.error(f"项目出错: {e}")
raise
practical_application()
# 6. 异常捕获示例
print("\n=== 6. 异常捕获示例 ===")
def exception_handling_example():
"""异常捕获示例"""
log_utils = LogUtils(root_path='./', log_name='exception_test')
logger = log_utils.get_log()
try:
logger.info("开始执行任务")
# 模拟可能出错的代码
result = 10 / 0 # 故意出错
except Exception as e:
logger.error(f"任务执行失败: {e}")
logger.error(f"错误类型: {type(e).__name__}")
print(f"错误已记录到日志: {e}")
exception_handling_example()
# 7. 日志使用规范
print("\n=== 7. 日志使用规范 ===")
def log_usage_specification():
"""日志使用规范"""
print("""
日志使用规范:
1. 不要使用print
- 使用logger.info()代替print()
- 便于统一管理
2. 合理使用日志级别
- DEBUG: 调试信息
- INFO: 正常流程
- WARNING: 警告
- ERROR: 错误
3. 使用try-except包裹代码
- 捕获异常
- 记录错误到日志
4. 测试代码位置
- 写到 if __name__ == '__main__': 中
- 避免导包时执行
5. 父目录设置
- 使用 './' 表示当前目录上一级
- 自动创建log目录
- 不要写 './log/'
""")
log_usage_specification()
# 8. 完整日志工具类
print("\n=== 8. 完整日志工具类 ===")
def complete_log_utils():
"""完整日志工具类"""
print("""
utils/log.py 完整代码:
import os
import logging
class LogUtils:
def __init__(self, root_path='./', log_name='project', level=logging.INFO):
self.logger = logging.getLogger(log_name)
self.logger.setLevel(level)
if not self.logger.handlers:
log_dir = os.path.join(root_path, 'log')
os.makedirs(log_dir, exist_ok=True)
log_file = os.path.join(log_dir, f'{log_name}.log')
file_handler = logging.FileHandler(log_file, encoding='utf-8')
file_handler.setLevel(level)
console_handler = logging.StreamHandler()
console_handler.setLevel(level)
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
self.logger.addHandler(file_handler)
self.logger.addHandler(console_handler)
def get_log(self):
return self.logger
# 使用方法
if __name__ == '__main__':
log_utils = LogUtils(root_path='./', log_name='power_load')
logger = log_utils.get_log()
logger.info("测试日志")
""")
complete_log_utils()
# 9. 日志功能总结
def log_function_summary():
"""日志功能总结"""
print("=" * 50)
print("日志功能总结")
print("=" * 50)
print("\n1. 日志级别")
print(" DEBUG < INFO < WARNING < ERROR < CRITICAL")
print("\n2. 日志工具类")
print(" utils/log.py")
print(" LogUtils类")
print("\n3. 使用方法")
print(" 创建对象 → 获取logger → 记录日志")
print("\n4. 父目录设置")
print(" 使用 './' 自动创建log目录")
print("\n5. 异常处理")
print(" try-except包裹代码")
print(" 错误记录到日志")
print("\n" + "=" * 50)
print("日志功能介绍完成!")
print("=" * 50)
log_function_summary()
输出示例:
=== 1. 日志工具类 ===
=== 3. 测试日志工具 ===
2024-01-01 12:00:00 - power_load - DEBUG - 这是DEBUG级别的日志
2024-01-01 12:00:00 - power_load - INFO - 这是INFO级别的日志
2024-01-01 12:00:00 - power_load - WARNING - 这是WARNING级别的日志
2024-01-01 12:00:00 - power_load - ERROR - 这是ERROR级别的日志
2024-01-01 12:00:00 - power_load - CRITICAL - 这是CRITICAL级别的日志
=== 6. 异常捕获示例 ===
错误已记录到日志: division by zero
5 重难点与易错提醒
- ❗重点:日志级别:DEBUG < INFO < WARNING < ERROR < CRITICAL。
- ❗重点:设置级别后,低于该级别的日志不打印。
- ❗重点:父目录用
./,自动创建log目录。 - ❗重点:测试代码写到
if __name__ == '__main__':中。 - ⚠️易错:父目录写成
./log/(会变成log/log/)。 - ⚠️易错:测试代码直接写在模块中。
- 💡深入理解:日志是工程化开发的基础。
6 课堂问答精选
Q: 日志有哪些级别?
A: 日志级别(从低到高):
- DEBUG:调试信息
- INFO:普通信息
- WARNING:警告信息
- ERROR:错误信息
- CRITICAL:严重错误
设置级别后,低于该级别的日志不打印。
Q: 父目录为什么要用./?
A:
./表示当前目录上一级- 自动创建log目录
- 如果写
./log/,会变成log/log/
7 本课小结
- 级别:DEBUG < INFO < WARNING < ERROR < CRITICAL。
- 工具类:LogUtils,get_log方法。
- 父目录:用
./,自动创建log目录。 - 测试代码:写到
if __name__ == '__main__':中。 - 异常处理:try-except包裹,记录错误。
8 延伸思考与实践
- 实践:配置日志工具类。
- 预习:数据预处理。
- 思考:日志级别如何选择?