网站首页 > 技术文章 正文
对话实录
小白:(满脸焦虑,疯狂翻着代码)专家救命!我的Python程序运行起来状况百出,用print调试时日志在终端窗口都刷没了,根本找不到问题出在哪,快教教我怎么办!
专家:(淡定一笑,敲了敲电脑)别慌!logging模块就是你的救星!它能像飞机黑匣子一样,精准记录程序运行的每一步,比print强大百倍,还能灵活控制输出。今天就带你玩转这个神器!
一、logging 基础:从 “记流水账” 开始
1.logging 的初体验
logging是 Python 内置的日志记录模块,默认只记录警告及以上级别的信息。简单一行代码,就能让程序 “开口说话”:
import logging
logging.warning('程序出现潜在风险!')
运行后,控制台会输出:
WARNING:root:程序出现潜在风险!
核心概念:
- 日志级别:从低到高分为DEBUG(调试信息)、INFO(运行信息)、WARNING(警告)、ERROR(错误)、CRITICAL(严重错误),级别越高越重要。
- 默认配置:不做额外设置时,日志输出到控制台,格式为级别:logger名称:日志内容。
2.调整日志 “音量”
通过basicConfig函数,能自由设置日志级别。比如想看到程序所有 “悄悄话”(DEBUG级信息),可以这样做:
import logging
# 设置日志级别为DEBUG,显示所有DEBUG及以上级别的信息
logging.basicConfig(level=logging.DEBUG)
logging.debug('这是一段调试信息,帮助定位问题')
logging.info('程序正在按计划执行')
logging.warning('注意!可能存在性能瓶颈')
logging.error('程序出现错误,部分功能失效')
logging.critical('系统崩溃,紧急修复!')
输出:
DEBUG:root:这是一段调试信息,帮助定位问题
INFO:root:程序正在按计划执行
WARNING:root:注意!可能存在性能瓶颈
ERROR:root:程序出现错误,部分功能失效
CRITICAL:root:系统崩溃,紧急修复!
二、进阶操作:定制专属日志系统
1.让日志 “住进” 文件,打造个性化日志 “模板”
不想让日志在控制台一闪而过?可以日志加上执行时间,函数名、行号等 “标签”,并把它们保存到文件,方便复盘分析
import logging
logging.basicConfig(
level=logging.DEBUG,
# 指定日志文件路径,文件会自动创建
filename='app.log',
# 'a'表示追加模式,新日志不会覆盖旧日志
filemode='a',
# 自定义日志格式,包含时间、级别、内容
format='%(asctime)s - %(name)s - %(levelname)s - %(funcName)s - %(lineno)d - %(message)s'
)
def divide(a, b):
try:
result = a / b
logging.info('除法运算成功')
return result
except ZeroDivisionError:
logging.error('除数不能为0', exc_info=True)
#增加exc_info=True:在日志中记录完整的异常堆栈信息,方便排查问题。
divide(10, 2)
divide(10, 0)
在app.log中输出:
2025-04-20 09:44:54,987 - root - INFO - divide - 125 - 除法运算成功
2025-04-20 09:44:54,987 - root - ERROR - divide - 128 - 除数不能为0
Traceback (most recent call last):
File "/Desktop/test.py", line 124, in divide
result = a / b
ZeroDivisionError: division by zero
格式说明:
- %(asctime)s:日志记录时间(如2025-04-20 09:42:20,284)
- %(name)s:日志记录用户(如root)
- %(levelname)s:日志级别(DEBUG/INFO等)
- %(funcName)s:函数名
- %(lineno)s:代码行号
- %(message)s:具体日志内容
2.多模块日志 “分区管理”
大型项目中,不同模块的日志容易 “打架”?通过使用FileHandler将不同模块的Logger分开管理:
import logging
def module_logging(module_name):
# 创建名为'module_name'的Logger
logger = logging.getLogger(module_name)
#设置级别为debug
logger.setLevel(logging.DEBUG)
# 创建文件处理器,专门记录module_name的日志到一个log文件
file_handler = logging.FileHandler(f'{module_name}.log')
file_handler.setLevel(logging.DEBUG)
#创建日志格式
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
# 将文件处理器添加到Logger
logger.addHandler(file_handler)
return logger
#定义两个module
module1_logger = module_logging('module1')
module2_logger = module_logging('module2')
#分别打印不同module的日志到对应日志文件
module1_logger.info('module1 的日志信息')
module2_logger.error('module2 的错误日志信息')
同时使用StreamHandler将error日志输出到控制器,这样我们就可以在程序执行窗口看到错误日志了。上面的代码改造为增加1个控制台处理器:
import logging
def module_logging(module_name):
logger = logging.getLogger(module_name)
logger.setLevel(logging.DEBUG)
file_handler = logging.FileHandler(f'{module_name}.log')
file_handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
# 创建控制台处理器,只显示ERROR及以上级别的信息
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.ERROR)
logger.addHandler(console_handler)
return logger
module1_logger = module_logging('module1')
module2_logger = module_logging('module2')
module1_logger.info('module1 的日志信息')
module2_logger.error('module2 的错误日志信息')
3.按日期滚动日志文件
使用TimedRotatingFileHandler可以实现按日期滚动日志文件,每天生成一个新的日志文件。
import logging
from logging.handlers import TimedRotatingFileHandler
logger = logging.getLogger('rotating_logger')
logger.setLevel(logging.DEBUG)
# 创建按天滚动的文件处理器
file_handler = TimedRotatingFileHandler('app.log', when='D', interval = 1, backupCount = 7)
file_handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
for i in range(10):
logger.debug(f'循环中日志 {i}')
TimedRotatingFileHandler('app.log', when='D', interval = 1, backupCount = 7) 创建了一个按天滚动的文件处理器。when='D' 表示按天滚动,interval = 1 表示每天滚动一次,backupCount = 7 表示最多保留 7 个旧的日志文件,超过 7 个旧文件会被删除。
4.按文件大小滚动日志文件
使用RotatingFileHandler可以实现按文件大小滚动日志文件。
import logging
from logging.handlers import RotatingFileHandler
logger = logging.getLogger('size_rotating_logger')
logger.setLevel(logging.DEBUG)
# 创建按文件大小滚动的文件处理器,最大1024字节,最多保留3个备份文件
file_handler = RotatingFileHandler('app.log', maxBytes = 1024, backupCount = 3)
file_handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
for i in range(1000):
logger.debug(f'循环中日志 {i}')
RotatingFileHandler('app.log', maxBytes = 1024, backupCount = 3) 创建了一个按文件大小滚动的文件处理器,当 app.log文件大小达到1024字节时,会创建新的备份文件,最多保留3个备份文件。
三、实战案例:logging的“十八般武艺”
案例 1:Web应用的 “健康监控”
在 Flask 应用中,用logging记录用户请求和错误:
from flask import Flask
import logging
app = Flask(__name__)
logging.basicConfig(
level=logging.INFO,
filename='flask_app.log',
format='%(asctime)s - %(levelname)s - %(message)s'
)
@app.route('/')
def index():
logging.info('用户访问首页')
return 'Hello, World!'
@app.errorhandler(404)
def page_not_found(error):
logging.error(f'404错误:{error}')
return '页面未找到', 404
if __name__ == '__main__':
app.run(debug=True)
通过分析flask_app.log,能快速定位高频访问页面和错误接口!
案例 2:自动化脚本的 “任务日记”
在脚本中记录任务执行的每一步:
import logging
import time
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
def backup_data():
logging.info('开始执行数据备份任务')
time.sleep(2)
try:
# 模拟备份操作
with open('backup.txt', 'w') as f:
f.write('备份成功')
logging.info('数据备份完成')
except Exception as e:
logging.error(f'备份失败:{e}')
backup_data()
即使脚本半夜运行,第二天也能通过日志了解任务执行过程!
案例 3:数据库操作的 “安全卫士”
在操作数据库时,记录关键操作和异常:
import logging
import sqlite3
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
def query_database():
try:
conn = sqlite3.connect('example.db')
cursor = conn.cursor()
cursor.execute('SELECT * FROM users')
result = cursor.fetchall()
logging.info(f'查询成功,结果:{result}')
conn.close()
except sqlite3.Error as e:
logging.error(f'数据库查询失败:{e}')
query_database()
一旦数据库出问题,日志立刻 “报警”!
闭坑指南:避开 logging 的 “雷区”
日志级别设置混乱
- 错误操作:设置过高的日志级别(如生产环境用CRITICAL),导致关键信息被 “屏蔽”。
- 正确姿势:开发阶段用DEBUG全面排查,生产环境切换为INFO或WARNING,聚焦核心问题。
日志文件 “无限膨胀”
- 错误操作:未设置日志文件大小限制,导致文件越来越大,撑爆硬盘。
- 正确姿势:使用RotatingFileHandler按大小或时间切割日志文件:
多模块日志 “串台”
- 错误操作:不同模块共用同一个Logger,日志混杂难以区分。
- 正确姿势:每个模块创建独立Logger,通过logger.name标识来源:
日志格式 “乱码”
- 错误操作:写入文件时未指定编码,导致中文等字符乱码。
- 正确姿势:在basicConfig中添加encoding='utf-8':
logging.basicConfig(
level=logging.INFO,
filename='app.log',
format='%(asctime)s - %(levelname)s - %(message)s',
encoding='utf-8'
)
五、专家总结:logging让代码 “有迹可循”
掌握logging,就像给程序安上了 “记录仪” 和 “指南针”!无论是调试Bug、监控运行状态,还是复盘历史操作,它都能轻松搞定。从现在开始,抛弃混乱的print,用logging让代码更专业、更健壮!
猜你喜欢
- 2025-05-16 Python随机模块22个函数详解
- 2025-05-16 Linux 命令 su 和 sudo 的区别?
- 2025-05-16 快速掌握Python时间函数的常用知识
- 2025-05-16 Java对比学习Python之高级特性:IO编程
- 2025-05-16 通俗地讲解Python的装饰器
- 2025-05-16 零起点Python机器学习快速入门-8-5-批量调用机器学习
- 2025-05-16 全网最详尽的Python遍历的高级用法,程序员必收藏!
- 2025-05-16 Python高级排序算法应用
- 2025-05-16 Python 惰性计算:让代码 “懒” 出高效与优雅
- 2025-05-16 人工智能数学基础2:指数、方根及对数运算公式
- 05-25Python 3.14 t-string 要来了,它与 f-string 有何不同?
- 05-25Python基础元素语法总结
- 05-25Python中的变量是什么东西?
- 05-25新手常见的python报错及解决方案
- 05-2511-Python变量
- 05-2510个每个人都是需要知道Python问题
- 05-25Python编程:轻松掌握函数定义、类型及其参数传递方式
- 05-25Python基础语法
- 257℃Python短文,Python中的嵌套条件语句(六)
- 257℃python笔记:for循环嵌套。end=""的作用,图形打印
- 256℃PythonNet:实现Python与.Net代码相互调用!
- 251℃Python操作Sqlserver数据库(多库同时异步执行:增删改查)
- 251℃Python实现字符串小写转大写并写入文件
- 106℃原来2025是完美的平方年,一起探索六种平方的算吧
- 91℃Python 和 JavaScript 终于联姻了!PythonMonkey 要火?
- 81℃Ollama v0.4.5-v0.4.7 更新集合:Ollama Python 库改进、新模型支持
- 最近发表
- 标签列表
-
- python中类 (31)
- python 迭代 (34)
- python 小写 (35)
- python怎么输出 (33)
- python 日志 (35)
- python语音 (31)
- python 工程师 (34)
- python3 安装 (31)
- python音乐 (31)
- 安卓 python (32)
- python 小游戏 (32)
- python 安卓 (31)
- python聚类 (34)
- python向量 (31)
- python大全 (31)
- python次方 (33)
- python桌面 (32)
- python总结 (34)
- python浏览器 (32)
- python 请求 (32)
- python 前端 (32)
- python验证码 (33)
- python 题目 (32)
- python 文件写 (33)
- python中的用法 (32)