xqqlyx

python logging四大组件使用示例

1. Logger

作用:日志的“入口”,负责创建和管理日志记录,可按模块/功能划分(如logger = logging.getLogger("module_a")),支持级别控制(低于设置级别的日志会被过滤),还存在父子Logger继承关系(子Logger默认向上传递日志给父Logger)。

示例1:创建模块级Logger并设置级别

import logging

# 创建Logger(推荐用模块名命名,便于区分日志来源)
logger_api = logging.getLogger("api_module")
logger_db = logging.getLogger("db_module")

# 设置级别:只处理INFO及以上日志
logger_api.setLevel(logging.INFO)
logger_db.setLevel(logging.DEBUG)

# 添加控制台Handler(用于输出)
console_handler = logging.StreamHandler()
logger_api.addHandler(console_handler)
logger_db.addHandler(console_handler)

logger_api.debug("API模块的DEBUG日志(被过滤,不输出)")
logger_api.info("API模块的INFO日志(输出)")
logger_db.debug("DB模块的DEBUG日志(输出)")

示例2:父子Logger继承(root是顶级父Logger)

import logging

# 父Logger:parent_logger
parent_logger = logging.getLogger("parent")
parent_logger.setLevel(logging.DEBUG)
parent_handler = logging.StreamHandler()
parent_logger.addHandler(parent_handler)

# 子Logger:parent.child(自动继承父Logger的Handler和级别)
child_logger = logging.getLogger("parent.child")

child_logger.info("子Logger的日志会传递给父Logger的Handler输出")  # 输出

2. Handler

作用:日志的“输出管道”,决定日志发送到哪里(控制台、文件、网络、邮件等),支持多Handler组合(一个Logger可绑定多个Handler,实现日志多端输出)。

示例1:输出到控制台(StreamHandler)

import logging

logger = logging.getLogger("console_logger")
logger.setLevel(logging.DEBUG)

# 创建控制台Handler
console_handler = logging.StreamHandler()  # 默认输出到sys.stderr
console_handler.setLevel(logging.DEBUG)  # Handler级别需≤Logger级别才生效

logger.addHandler(console_handler)
logger.debug("控制台输出的DEBUG日志")

示例2:输出到文件(FileHandler/RotatingFileHandler)

import logging
from logging.handlers import RotatingFileHandler

logger = logging.getLogger("file_logger")
logger.setLevel(logging.INFO)

# 基础文件Handler(写入单个文件)
# file_handler = logging.FileHandler("app.log", encoding="utf-8")

# 轮转文件Handler(避免文件过大,单个文件10MB,保留5个备份)
rotating_handler = RotatingFileHandler(
    "app_rotate.log",
    maxBytes=10*1024*1024,  # 10MB
    backupCount=5,
    encoding="utf-8"
)

logger.addHandler(rotating_handler)
logger.info("写入到轮转文件的INFO日志")

示例3:输出到网络(SocketHandler,通过TCP发送日志)

import logging
from logging.handlers import SocketHandler

logger = logging.getLogger("network_logger")
logger.setLevel(logging.ERROR)

# 创建SocketHandler(连接到远程日志服务器的IP和端口)
socket_handler = SocketHandler("127.0.0.1", 9000)  # 需提前启动日志服务器监听9000端口
logger.addHandler(socket_handler)

logger.error("通过TCP发送到远程服务器的ERROR日志")

补充:若需HTTP协议发送,可使用HTTPHandler

from logging.handlers import HTTPHandler
http_handler = HTTPHandler("127.0.0.1:8000", "/log", method="POST")
logger.addHandler(http_handler)

3. Formatter

作用:日志的“格式化工具”,定义日志输出的样式(如包含时间、模块名、行号、日志级别等),需绑定到Handler使用(一个Handler只能绑定一个Formatter,不同Handler可绑定不同Formatter)。

示例1:基础格式(时间+级别+消息)

import logging

logger = logging.getLogger("basic_formatter")
logger.setLevel(logging.INFO)

console_handler = logging.StreamHandler()
# 定义Formatter:%(asctime)s(时间)、%(levelname)s(级别)、%(message)s(消息)
basic_formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
console_handler.setFormatter(basic_formatter)

logger.addHandler(console_handler)
logger.info("基础格式的日志输出")
# 输出示例:2025-12-02 15:30:00 - INFO - 基础格式的日志输出

示例2:详细格式(含模块、行号、进程ID)

import logging

logger = logging.getLogger("detail_formatter")
logger.setLevel(logging.DEBUG)

file_handler = logging.FileHandler("detail.log", encoding="utf-8")
# 详细格式:模块名+行号+进程ID+线程名+日志内容
detail_formatter = logging.Formatter(
    "%(asctime)s - %(module)s:%(lineno)d - %(process)d:%(threadName)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"  # 自定义时间格式
)
file_handler.setFormatter(detail_formatter)

logger.addHandler(file_handler)
logger.debug("详细格式的DEBUG日志")
# 输出示例:2025-12-02 15:35:00 - demo:10 - 12345:MainThread - DEBUG - 详细格式的DEBUG日志

示例3:不同Handler绑定不同Formatter

import logging

logger = logging.getLogger("multi_formatter")
logger.setLevel(logging.DEBUG)

# 控制台Handler用简单格式
console_handler = logging.StreamHandler()
console_formatter = logging.Formatter("%(levelname)s - %(message)s")
console_handler.setFormatter(console_formatter)

# 文件Handler用详细格式
file_handler = logging.FileHandler("multi.log", encoding="utf-8")
file_formatter = logging.Formatter("%(asctime)s - %(module)s - %(levelname)s - %(message)s")
file_handler.setFormatter(file_formatter)

logger.addHandler(console_handler)
logger.addHandler(file_handler)
logger.info("控制台显示简单格式,文件显示详细格式")

4. Filter

作用:日志的“筛选器”,实现比级别更细粒度的日志控制(如只允许特定模块、特定内容、特定用户的日志通过),可绑定到Logger或Handler上。

示例1:按模块筛选(只允许特定模块的日志)

import logging

class ModuleFilter(logging.Filter):
    """自定义Filter:只允许'module_order'模块的日志"""
    def filter(self, record):  # record是日志记录对象,包含name/levelno/message等属性
        return record.name == "module_order"

logger_order = logging.getLogger("module_order")
logger_pay = logging.getLogger("module_pay")

console_handler = logging.StreamHandler()
console_handler.addFilter(ModuleFilter())  # 绑定到Handler

logger_order.addHandler(console_handler)
logger_pay.addHandler(console_handler)

logger_order.info("订单模块日志(通过筛选,输出)")
logger_pay.info("支付模块日志(被过滤,不输出)")

示例2:按内容+级别筛选(只允许包含"ERROR"且级别≥ERROR的日志)

import logging

class ContentLevelFilter(logging.Filter):
    def filter(self, record):
        return record.levelno >= logging.ERROR and "ERROR" in record.message

logger = logging.getLogger("content_filter")
logger.setLevel(logging.DEBUG)

console_handler = logging.StreamHandler()
console_handler.addFilter(ContentLevelFilter())
logger.addHandler(console_handler)

logger.error("ERROR: 数据库连接失败(符合条件,输出)")
logger.warning("WARNING: 配置缺失(级别不够,不输出)")
logger.error("数据校验失败(不含'ERROR',不输出)")

示例3:绑定到Logger的Filter(全局筛选)

import logging

class LevelFilter(logging.Filter):
    """只允许INFO级别日志"""
    def filter(self, record):
        return record.levelno == logging.INFO

logger = logging.getLogger("logger_filter")
logger.addFilter(LevelFilter())  # 绑定到Logger,所有Handler都会应用此Filter
logger.setLevel(logging.DEBUG)

console_handler = logging.StreamHandler()
logger.addHandler(console_handler)

logger.debug("DEBUG日志(被过滤)")
logger.info("INFO日志(输出)")
logger.warning("WARNING日志(被过滤)")

posted on 2025-12-02 19:56  烫烫烫烫热  阅读(6)  评论(0)    收藏  举报