Python logging
在编程中,日志记录(logging)是一种非常重要的工具,它可以帮助我们跟踪程序的运行状态、调试错误以及记录重要信息。
Python 提供了一个内置的 logging 模块,专门用于处理日志记录任务。与简单的 print 语句相比,logging 模块更加灵活和强大,能够满足不同场景下的日志需求。
为什么使用 logging 模块?
- 灵活性:logging 模块允许你根据需要设置日志的级别、格式和输出位置。
- 可扩展性:你可以轻松地将日志输出到文件、控制台、网络等不同的目标。
- 结构化日志:logging 模块支持结构化日志记录,便于后续的分析和处理。
- 性能优化:与 print 相比,logging 模块在性能上进行了优化,适合在生产环境中使用。
logging 模块的基本用法
- 导入 logging 模块
首先,我们需要导入 logging 模块:
实例
import logging
- 配置日志级别
日志级别用于控制日志的详细程度。logging 模块提供了以下几种日志级别:
DEBUG:详细的调试信息,通常用于开发阶段。
INFO:程序正常运行时的信息。
WARNING:表示潜在的问题,但程序仍能正常运行。
ERROR:表示程序中的错误,导致某些功能无法正常工作。
CRITICAL:表示严重的错误,可能导致程序崩溃。
你可以通过以下代码设置日志级别:
实例
logging.basicConfig(level=logging.DEBUG)
- 记录日志
设置好日志级别后,你可以使用以下方法记录日志:
实例
logging.debug("这是一条调试信息")
logging.info("这是一条普通信息")
logging.warning("这是一条警告信息")
logging.error("这是一条错误信息")
logging.critical("这是一条严重错误信息")
- 日志输出格式
你可以通过 basicConfig 方法自定义日志的输出格式。例如:
实例
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
- 将日志输出到文件
默认情况下,日志会输出到控制台。如果你希望将日志保存到文件中,可以这样配置:
实例
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
filename="app.log"
)
简单使用的日志记录
"""
简单实用的日志记录器
快速上手版本
"""
import logging
from datetime import datetime
# 快速配置日志
def setup_logger(log_file='output.txt'):
"""
快速设置日志记录器
Args:
log_file: 日志文件名
Returns:
配置好的logger对象
"""
# 创建logger
logger = logging.getLogger('MyLogger')
logger.setLevel(logging.DEBUG)
logger.handlers.clear()
# 文件处理器
file_handler = logging.FileHandler(log_file, encoding='utf-8', mode='a')
file_handler.setLevel(logging.DEBUG)
# 格式
formatter = logging.Formatter(
'%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return logger
# 创建全局logger
logger = setup_logger('output.txt')
# 示例函数1:简单计算
def add_numbers(a, b):
"""加法函数"""
logger.info(f"执行加法: {a} + {b}")
result = a + b
logger.info(f"结果: {result}")
return result
# 示例函数2:列表处理
def process_list(items):
"""处理列表"""
logger.info(f"开始处理列表,共 {len(items)} 项")
results = []
for i, item in enumerate(items, 1):
logger.debug(f"处理第 {i} 项: {item}")
results.append(item * 2)
logger.info(f"处理完成,结果: {results}")
return results
# 示例函数3:带异常处理
def safe_divide(a, b):
"""安全除法"""
logger.info(f"执行除法: {a} / {b}")
try:
result = a / b
logger.info(f"结果: {result}")
return result
except ZeroDivisionError:
logger.error("错误: 除数不能为0")
return None
except Exception as e:
logger.error(f"未知错误: {e}")
return None
# 测试
if __name__ == "__main__":
logger.info("=" * 50)
logger.info("程序开始运行")
logger.info("=" * 50)
# 测试1
add_numbers(5, 3)
# 测试2
process_list([1, 2, 3, 4, 5])
# 测试3
safe_divide(10, 2)
safe_divide(10, 0)
logger.info("=" * 50)
logger.info("程序运行结束")
logger.info("=" * 50)
print("\n日志已保存到 output.txt")
日志函数完整示例
"""
Python 日志模块完整示例
演示如何记录函数执行过程到文件
"""
import logging
import functools
from datetime import datetime
import traceback
# ============================================
# 1. 基础日志配置
# ============================================
def setup_basic_logger():
"""基础日志配置 - 记录到文件"""
logging.basicConfig(
filename='app.log',
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 测试
logging.debug('这是调试信息')
logging.info('这是普通信息')
logging.warning('这是警告信息')
logging.error('这是错误信息')
logging.critical('这是严重错误')
# ============================================
# 2. 高级日志配置 - 同时输出到文件和控制台
# ============================================
def setup_advanced_logger(log_file='function_logs.txt'):
"""创建高级日志记录器"""
# 创建logger
logger = logging.getLogger('FunctionLogger')
logger.setLevel(logging.DEBUG)
# 清除已有的处理器(避免重复)
logger.handlers.clear()
# 文件处理器
file_handler = logging.FileHandler(log_file, encoding='utf-8')
file_handler.setLevel(logging.DEBUG)
# 控制台处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 格式化器
detailed_formatter = logging.Formatter(
'%(asctime)s | %(levelname)-8s | %(funcName)s | %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
file_handler.setFormatter(detailed_formatter)
console_handler.setFormatter(detailed_formatter)
# 添加处理器
logger.addHandler(file_handler)
logger.addHandler(console_handler)
return logger
# ============================================
# 3. 装饰器 - 自动记录函数执行
# ============================================
def log_function_call(logger):
"""装饰器:自动记录函数调用"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
# 记录函数开始
logger.info(f"开始执行函数: {func.__name__}")
logger.debug(f"参数: args={args}, kwargs={kwargs}")
try:
# 执行函数
result = func(*args, **kwargs)
# 记录成功
logger.info(f"函数 {func.__name__} 执行成功")
logger.debug(f"返回值: {result}")
return result
except Exception as e:
# 记录异常
logger.error(f"函数 {func.__name__} 执行失败: {str(e)}")
logger.error(f"异常详情:\n{traceback.format_exc()}")
raise
return wrapper
return decorator
# ============================================
# 4. 实际应用示例
# ============================================
# 创建全局logger
logger = setup_advanced_logger('function_logs.txt')
@log_function_call(logger)
def calculate_sum(a, b):
"""计算两数之和"""
logger.info(f"正在计算 {a} + {b}")
result = a + b
return result
@log_function_call(logger)
def divide_numbers(a, b):
"""除法运算"""
logger.info(f"正在计算 {a} / {b}")
if b == 0:
logger.warning("检测到除数为0")
raise ValueError("除数不能为0")
result = a / b
return result
@log_function_call(logger)
def process_data(data_list):
"""处理数据列表"""
logger.info(f"开始处理 {len(data_list)} 条数据")
results = []
for i, item in enumerate(data_list):
logger.debug(f"处理第 {i+1} 项: {item}")
results.append(item * 2)
logger.info(f"数据处理完成,共 {len(results)} 条结果")
return results
# ============================================
# 5. 带上下文的日志记录
# ============================================
class LogContext:
"""日志上下文管理器"""
def __init__(self, logger, operation_name):
self.logger = logger
self.operation_name = operation_name
self.start_time = None
def __enter__(self):
self.start_time = datetime.now()
self.logger.info(f"=== 开始操作: {self.operation_name} ===")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
duration = (datetime.now() - self.start_time).total_seconds()
if exc_type is None:
self.logger.info(f"=== 操作完成: {self.operation_name} (耗时: {duration:.2f}秒) ===")
else:
self.logger.error(f"=== 操作失败: {self.operation_name} (耗时: {duration:.2f}秒) ===")
self.logger.error(f"异常: {exc_val}")
return False # 不抑制异常
def complex_operation():
"""复杂操作示例"""
with LogContext(logger, "复杂数据处理"):
logger.info("步骤1: 加载数据")
data = [1, 2, 3, 4, 5]
logger.info("步骤2: 处理数据")
processed = process_data(data)
logger.info("步骤3: 计算总和")
total = calculate_sum(sum(processed), 10)
return total
# ============================================
# 6. 按日期分割日志文件
# ============================================
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
def setup_rotating_logger():
"""创建按大小或时间轮转的日志"""
logger = logging.getLogger('RotatingLogger')
logger.setLevel(logging.DEBUG)
logger.handlers.clear()
# 按大小轮转 (每个文件最大1MB,保留3个备份)
size_handler = RotatingFileHandler(
'app_size.log',
maxBytes=1024*1024, # 1MB
backupCount=3,
encoding='utf-8'
)
# 按时间轮转 (每天一个新文件,保留7天)
time_handler = TimedRotatingFileHandler(
'app_daily.log',
when='midnight',
interval=1,
backupCount=7,
encoding='utf-8'
)
formatter = logging.Formatter(
'%(asctime)s - %(levelname)s - %(message)s'
)
size_handler.setFormatter(formatter)
time_handler.setFormatter(formatter)
logger.addHandler(size_handler)
logger.addHandler(time_handler)
return logger
# ============================================
# 7. 主程序 - 测试所有功能
# ============================================
if __name__ == "__main__":
print("开始测试日志功能...\n")
# 测试基本函数
print("1. 测试基本函数调用")
result1 = calculate_sum(10, 20)
print(f"结果: {result1}\n")
# 测试数据处理
print("2. 测试数据处理")
result2 = process_data([1, 2, 3, 4, 5])
print(f"结果: {result2}\n")
# 测试异常处理
print("3. 测试异常处理")
try:
divide_numbers(10, 0)
except ValueError as e:
print(f"捕获异常: {e}\n")
# 测试正常除法
print("4. 测试正常除法")
result3 = divide_numbers(10, 2)
print(f"结果: {result3}\n")
# 测试复杂操作
print("5. 测试复杂操作")
result4 = complex_operation()
print(f"结果: {result4}\n")
print("=" * 50)
print("所有日志已记录到 function_logs.txt")
print("请查看文件内容")
使用装饰器记录函数执行
"""
使用装饰器自动记录函数执行
最方便的方式
"""
import logging
import functools
import time
# 配置日志
logging.basicConfig(
filename='auto_log.txt',
level=logging.DEBUG,
format='%(asctime)s | %(levelname)s | %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
encoding='utf-8'
)
logger = logging.getLogger(__name__)
# 装饰器:自动记录函数
def auto_log(func):
"""
装饰器:自动记录函数的输入、输出和执行时间
使用方法:
@auto_log
def my_function(a, b):
return a + b
"""
@functools.wraps(func)
def wrapper(*args, **kwargs):
# 记录开始
logger.info(f"▶ 调用函数: {func.__name__}")
logger.debug(f" 参数: {args} {kwargs}")
start_time = time.time()
try:
# 执行函数
result = func(*args, **kwargs)
# 记录成功
elapsed = time.time() - start_time
logger.info(f"✓ 函数 {func.__name__} 执行成功 (耗时: {elapsed:.3f}秒)")
logger.debug(f" 返回值: {result}")
return result
except Exception as e:
# 记录失败
elapsed = time.time() - start_time
logger.error(f"✗ 函数 {func.__name__} 执行失败 (耗时: {elapsed:.3f}秒)")
logger.error(f" 错误: {type(e).__name__}: {e}")
raise
return wrapper
# ============================================
# 使用示例
# ============================================
@auto_log
def calculate(a, b, operation='+'):
"""计算器函数"""
if operation == '+':
return a + b
elif operation == '-':
return a - b
elif operation == '*':
return a * b
elif operation == '/':
return a / b
else:
raise ValueError(f"不支持的操作: {operation}")
@auto_log
def fetch_user_data(user_id):
"""模拟获取用户数据"""
logger.info(f" 正在查询用户 {user_id} 的数据...")
time.sleep(0.5) # 模拟网络延迟
# 模拟数据
user_data = {
'id': user_id,
'name': f'User_{user_id}',
'email': f'user{user_id}@example.com'
}
logger.info(f" 找到用户: {user_data['name']}")
return user_data
@auto_log
def process_batch(items):
"""批量处理数据"""
logger.info(f" 开始批量处理 {len(items)} 条数据")
results = []
for i, item in enumerate(items, 1):
logger.debug(f" 处理 {i}/{len(items)}: {item}")
results.append(item ** 2)
time.sleep(0.1)
logger.info(f" 批量处理完成")
return results
@auto_log
def risky_operation(value):
"""可能失败的操作"""
if value < 0:
raise ValueError("值不能为负数")
return value * 10
# ============================================
# 测试
# ============================================
if __name__ == "__main__":
print("开始执行,日志记录到 auto_log.txt\n")
# 测试1: 基本计算
print("1. 基本计算")
calculate(10, 5, '+')
calculate(10, 5, '*')
# 测试2: 获取数据
print("\n2. 获取用户数据")
user = fetch_user_data(123)
print(f" 获取到: {user}")
# 测试3: 批量处理
print("\n3. 批量处理")
results = process_batch([1, 2, 3, 4, 5])
print(f" 结果: {results}")
# 测试4: 异常处理
print("\n4. 测试异常")
try:
risky_operation(-5)
except ValueError as e:
print(f" 捕获异常: {e}")
# 测试5: 除零错误
print("\n5. 测试除零")
try:
calculate(10, 0, '/')
except ZeroDivisionError as e:
print(f" 捕获异常: {e}")
print("\n" + "="*50)
print("所有操作已记录到 auto_log.txt")
print("="*50)

浙公网安备 33010602011771号