Python脚本如何记录完整运行日志:从入门到生产级实践指南
📑 目录导读
- 为什么需要完整运行日志?——记录的价值与场景
- Python日志核心模块:logging详解——从基础配置到高级用法
- 生产级日志方案——含时间戳、文件轮转、多模块支持
- 常见问题与排查技巧——FAQ问答部分
- 最佳实践总结——SEO优化建议与代码模板
为什么需要完整运行日志?——记录的价值与场景
Q:Python脚本中,直接print()不好吗?为什么要专门记录日志?
A: 在生产环境中,print()输出存在致命缺陷:无法分级、无法持久化到文件、无法自动轮转、多线程输出混乱,完整日志能实现:

- 问题追溯:通过时间戳定位错误发生时刻
- 性能监控:记录关键节点的执行耗时
- 审计合规:保存所有操作的历史轨迹
- 自动告警:基于ERROR/WARNING级别触发通知
真实案例:某电商爬虫脚本每天运行,因未记录日志,偶然中断后无法定位是IP被封还是网站改版,加入日志后,通过CRITICAL级错误立即定位到反爬机制变更。
Python日志核心模块:logging详解
1 最小化配置(3行搞定)
import logging
logging.basicConfig(level=logging.INFO)
logging.info("脚本启动成功")
2 分级输出(DEBUG/INFO/WARNING/ERROR/CRITICAL)
logging.debug("调试信息:变量x=10") # 级别1,默认不输出
logging.info("用户登录成功") # 级别2
logging.warning("磁盘空间剩余<10%") # 级别3
logging.error("数据库连接失败") # 级别4
logging.critical("系统崩溃,需人工干预") # 级别5
3 自定义格式(时间戳+模块名+行号)
FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s' logging.basicConfig(format=FORMAT, level=logging.DEBUG)
示例输出:2025-04-08 14:30:00,123 - root - ERROR - main.py:42 - 文件未找到
生产级日志方案——文件轮转与持久化
1 记录到文件(自动创建、按大小轮转)
import logging
from logging.handlers import RotatingFileHandler
# 创建日志记录器
logger = logging.getLogger('my_app')
logger.setLevel(logging.DEBUG)
# 控制台输出
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.WARNING)
# 文件轮转(单文件5MB,保留3个备份)
file_handler = RotatingFileHandler('app.log', maxBytes=5*1024*1024, backupCount=3)
file_handler.setLevel(logging.DEBUG)
# 格式定义
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
# 加入处理器
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# 使用示例
logger.info("脚本开始运行")
try:
1/0
except Exception as e:
logger.error("发生除零错误", exc_info=True) # 自动记录完整堆栈
2 高级配置:多模块日志(推荐用字典配置)
# logging_config.yaml
version: 1
formatters:
detailed:
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
file:
class: logging.handlers.RotatingFileHandler
filename: production.log
maxBytes: 10485760 # 10MB
backupCount: 5
loggers:
my_module:
level: DEBUG
handlers: [file]
propagate: no
root:
level: INFO
handlers: [file]
3 性能优化:异步日志(防止阻塞)
from concurrent.futures import ThreadPoolExecutor
executor = ThreadPoolExecutor(max_workers=2)
def async_log(level, message):
executor.submit(getattr(logger, level), message)
async_log('info', '非阻塞日志记录')
常见问题与排查技巧(FAQ)
Q1:为什么我写了日志但是没有输出到文件?
- 检查点1:确认设置了
level=logging.DEBUG(默认只输出WARNING及以上) - 检查点2:确认文件路径有写入权限(如
/var/log/需sudo) - 检查点3:
RotatingFileHandler需指定绝对路径更可靠
Q2:日志文件越来越大怎么办?
- 方案A:使用
TimedRotatingFileHandler按天/小时轮转 - 方案B:设置
backupCount=5,自动删除旧日志
Q3:如何记录异常堆栈信息?
logger.error("数据库查询失败", exc_info=True)
# 或更简洁:
logger.exception("数据库查询失败") # 自动包含exc_info
Q4:多个Python文件怎么共享同一个日志配置?
# 在 main.py 中初始化
logging.config.fileConfig('logging.conf')
from other_module import function
# other_module 中直接用 logging.getLogger(__name__) 获取实例
最佳实践总结——SEO优化与代码模板
🌟 黄金三原则
- 分体式配置:将日志配置与业务逻辑分离(推荐YAML/JSON)
- 分级别记录:INFO记录正常运行,ERROR记录异常,DEBUG调试用(生产环境禁用)
- 结构化输出:使用JSON格式方便日志分析工具(如ELK)
import json class JsonFormatter(logging.Formatter): def format(self, record): return json.dumps({ 'time': self.formatTime(record), 'level': record.levelname, 'message': record.getMessage(), 'module': record.module, 'line': record.lineno })
🚀 快速启动模板(复制即用)
import logging
from logging.handlers import RotatingFileHandler
def setup_logger(name='app', log_file='run.log'):
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
handler = RotatingFileHandler(log_file, maxBytes=10*1024*1024, backupCount=3)
handler.setFormatter(logging.Formatter(
'%(asctime)s | %(levelname)-8s | %(module)s:%(lineno)d | %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
))
logger.addHandler(handler)
return logger
# 使用
logger = setup_logger()
logger.info("脚本启动完成,开始处理任务...")
📈 SEO优化建议关键词**:Python日志、logging完整记录、生产级日志方案
- 内链策略:文中关于
RotatingFileHandler、logging.exception等术语已做自然融入深度**:覆盖从基础到高阶(异步日志、JSON格式化) - 实用性:提供可直接复用的代码块,符合Google E-A-T原则