Python logging

在编程中,日志记录(logging)是一种非常重要的工具,它可以帮助我们跟踪程序的运行状态、调试错误以及记录重要信息。

Python 提供了一个内置的 logging 模块,专门用于处理日志记录任务。与简单的 print 语句相比,logging 模块更加灵活和强大,能够满足不同场景下的日志需求。

为什么使用 logging 模块?

  • 灵活性:logging 模块允许你根据需要设置日志的级别、格式和输出位置。
  • 可扩展性:你可以轻松地将日志输出到文件、控制台、网络等不同的目标。
  • 结构化日志:logging 模块支持结构化日志记录,便于后续的分析和处理。
  • 性能优化:与 print 相比,logging 模块在性能上进行了优化,适合在生产环境中使用。

logging 模块的基本用法

  1. 导入 logging 模块
    首先,我们需要导入 logging 模块:

实例

import logging
  1. 配置日志级别
    日志级别用于控制日志的详细程度。logging 模块提供了以下几种日志级别:

DEBUG:详细的调试信息,通常用于开发阶段。
INFO:程序正常运行时的信息。
WARNING:表示潜在的问题,但程序仍能正常运行。
ERROR:表示程序中的错误,导致某些功能无法正常工作。
CRITICAL:表示严重的错误,可能导致程序崩溃。
你可以通过以下代码设置日志级别:

实例

logging.basicConfig(level=logging.DEBUG)
  1. 记录日志
    设置好日志级别后,你可以使用以下方法记录日志:

实例

logging.debug("这是一条调试信息")
logging.info("这是一条普通信息")
logging.warning("这是一条警告信息")
logging.error("这是一条错误信息")
logging.critical("这是一条严重错误信息")
  1. 日志输出格式
    你可以通过 basicConfig 方法自定义日志的输出格式。例如:

实例

logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
)
  1. 将日志输出到文件
    默认情况下,日志会输出到控制台。如果你希望将日志保存到文件中,可以这样配置:

实例

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)


posted @ 2025-12-02 16:39  乐乐乐乐乐乐樂  阅读(0)  评论(0)    收藏  举报
jQuery火箭图标返回顶部代码