【Python】Python日志库

参考

核心概念

1. Logging模块的基本组成

  • Logger: 日志记录器,负责捕获日志消息
  • Handler: 处理器,指定日志输出的目标(如控制台、文件、远程服务器)
  • Formatter: 格式化器,定义输出格式
  • Filter: 过滤器,用于日志消息进行筛选

2. 日志级别

  • DEBUG: 调试消息,用于开发阶段使用
  • INFO: 程序正常运行时的消息
  • WARRING: 程序运行中出现潜在问题,但是不会影响程序运行
  • ERROR: 程序运行中出现错误
  • CRITICAL: 严重错误,可能导致程序崩溃

3. 配置文件的使用与动态调整

通过配置文件(如 JSON 或 YAML)可以灵活地管理日志设置,支持动态调整日志级别和输出目标。

4. 日志轮转与存储优化

日志文件可能会迅速增长,导致磁盘空间不足。RotatingFileHandlerTimedRotatingFileHandler 提供了日志轮转功能,可按大小或时间分割日志文件。

应用场景

1. 代码配置本地终端日志和文件日志

import logging
from logging.handlers import RotatingFileHandler


def setup_logger():
    logger = logging.getLogger("web_logger")
    logger.setLevel(logging.DEBUG)

    handler = RotatingFileHandler("access.log", maxBytes=1024 * 1024, backupCount=5)
    handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))

    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.DEBUG)
    console_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
    logger.addHandler(handler)
    logger.addHandler(console_handler)
    return logger


logger = setup_logger()

if __name__ == "__main__":
    logger.info("Info")

2. 通过配置文件配置

import json
import logging
import logging.config
import os
import sys


# 加载日志配置文件
def setup_logging(config_file):
    """
    从 JSON 配置文件加载日志设置。
    """
    try:
        if not os.path.exists(config_file):
            raise FileNotFoundError(f"配置文件 {config_file} 未找到。")

        with open(config_file, "r", encoding="utf-8") as f:
            config = json.load(f)

        # 应用配置
        logging.config.dictConfig(config)
        print(f"成功加载日志配置: {config_file}")
    except json.JSONDecodeError as e:
        sys.stderr.write(f"配置文件格式错误: {e}\n")
        sys.exit(1)
    except Exception as e:
        sys.stderr.write(f"设置日志时出错: {e}\n")
        sys.exit(1)


# 使用更安全的方式初始化日志
def initialize_logging():
    try:
        setup_logging("docs\logger_config.json")
        return logging.getLogger("app_logger")
    except Exception as e:
        # 如果配置失败,设置基本日志
        print(f"使用默认日志配置: {e}")
        logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
        return logging.getLogger("app_logger")


# 初始化日志
logger = initialize_logging()


# 示例函数:模拟程序运行
def simulate_application():
    try:
        logger.debug("这是一条调试信息。")  # 控制台和文件中可见
        logger.info("这是一条信息消息。")  # 控制台和文件中可见
        logger.warning("这是一条警告消息。")  # 控制台和文件中可见
        logger.error("这是一条错误消息。")  # 控制台、文件和远程服务器中可见
        logger.critical("这是一条严重错误消息。")  # 控制台、文件和远程服务器中可见

        # 模拟一个异常情况
        try:
            result = 10 / 0
        except Exception as e:
            logger.exception(f"发生异常: {e}")
    except Exception as e:
        print(f"记录日志时出错: {e}")


if __name__ == "__main__":
    simulate_application()
    print("日志测试完成。请检查日志文件和远程服务器。")

    # 为了确保所有日志都被发送,特别是通过网络
    logging.shutdown()

配置文件

{
    "version": 1,
    "disable_existing_loggers": false,
    "formatters": {
      "detailed": {
        "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
      },
      "simple": {
        "format": "%(levelname)s - %(message)s"
      }
    },
    "handlers": {
      "console": {
        "class": "logging.StreamHandler",
        "level": "DEBUG",
        "formatter": "simple",
        "stream": "ext://sys.stdout"
      },
      "file": {
        "class": "logging.handlers.RotatingFileHandler",
        "level": "INFO",
        "formatter": "detailed",
        "filename": "app.log",
        "maxBytes": 1048576,
        "backupCount": 3
      },
      "remote": {
        "class": "logging.handlers.SocketHandler",
        "level": "ERROR",
        "host": "localhost",
        "port": 9020
      }
    },
    "loggers": {
      "app_logger": {
        "level": "DEBUG",
        "handlers": ["console", "file", "remote"],
        "propagate": false
      }
    },
    "root": {
      "level": "WARNING",
      "handlers": ["console"]
    }
  }
  

这里的app_logger是 对应return logging.getLogger("app_logger") 这两个名字要填对,不然就是使用 root的配置

格式输出

1.输出线程号+日期+代码位置

配置文件:

{
    "version": 1,
    "disable_existing_loggers": false,
    "formatters": {
        "detailed": {
            "format": "%(asctime)s | %(threadName)s | %(filename)s:%(lineno)d | %(levelname)s | %(message)s",
            "datefmt": "%Y-%m-%d %H:%M:%S"
        },
        "simple": {
            "format": "[%(levelname)s] %(message)s"
        }
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "level": "DEBUG",
            "formatter": "detailed",
            "stream": "ext://sys.stdout"
        },
        "file": {
            "class": "logging.handlers.TimedRotatingFileHandler",
            "level": "INFO",
            "formatter": "detailed",
            "filename": "app.log",
            "when": "midnight",
            "backupCount": 7,
            "encoding": "utf8"
        },
        "remote": {
            "class": "logging.handlers.SocketHandler",
            "level": "ERROR",
            "host": "localhost",
            "port": 9020
        }
    },
    "loggers": {
        "app_logger": {
            "level": "DEBUG",
            "handlers": ["console", "file", "remote"],
            "propagate": false
        }
    },
    "root": {
        "level": "WARNING",
        "handlers": ["console"]
    }
}

2025-03-22 17:52:56 | MainThread | logger.py:50 | DEBUG | 这是一条调试信息。
2025-03-22 17:52:56 | MainThread | logger.py:51 | INFO | 这是一条信息消息。
2025-03-22 17:52:56 | MainThread | logger.py:52 | WARNING | 这是一条警告消息。
2025-03-22 17:52:56 | MainThread | logger.py:53 | ERROR | 这是一条错误消息。
2025-03-22 17:52:58 | MainThread | logger.py:54 | CRITICAL | 这是一条严重错误消息。
2025-03-22 17:53:00 | MainThread | logger.py:60 | ERROR | 发生异常: division by zero

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值