您的位置:

以 Python 日志为中心的开发实践

Python 是一门广泛用于开发的高级编程语言,其强大的日志功能是让开发者更加便捷进行调试的关键所在。不同的应用场景需要不同的日志系统,Python 提供了一系列完善的日志库和方便易用的工具来帮助解决不同场景下的日志需求,这让 Python 的日志模块成为了 Python 编程中不可或缺的一部分。

一、Python 日志模块

Python 日志模块是 Python 标准库中的一部分,通过简单的调用就可以方便地实现日志的记录,对于 Python 开发者来说是一个非常重要的日志系统。Python 日志模块的主要是由五大部分构成:Logger,Handler,Filter,Formatter 和 LogRecord。

下面是一个简单的 Python 日志模块的示例:

import logging

# 创建一个logger
logger = logging.getLogger('mylogger')
logger.setLevel(logging.DEBUG)

# 创建一个handler,用于写入日志文件
fh = logging.FileHandler('test.log')
fh.setLevel(logging.DEBUG)

# 创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)

# 创建一个formatter,定义日志输出格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)

# 将handler添加到logger,日志即可输出到该handler中
logger.addHandler(fh)
logger.addHandler(ch)

# 记录一条debug级别的日志
logger.debug('This is a debug message')
# 记录一条info级别的日志
logger.info('This is an info message')
# 记录一条warning级别的日志
logger.warning('This is a warning message')
# 记录一条error级别的日志
logger.error('This is an error message')
# 记录一条critical级别的日志
logger.critical('This is a critical message')

该示例代码通过调用 Python 的 logging 模块,并使用 getLogger() 方法创建一个 logger 对象,然后再添加不同级别的 handler,最后使用 logger 以不同级别记录日志信息。

二、Python logging 模块的常用属性和方法

Logger 对象:

Logger.setLevel(level):设置日志级别。

Logger.addHandler(hdlr):为该 logger 对象添加一个 handler。

Logger.removeHandler(hdlr):为该 logger 对象删除一个 handler。

Handler 对象:

Handler.setLevel(level):设置 handler 对象的日志级别。

Handler.setFormatter(fmt):为 handler 对象设置日志格式。

Filter 对象:

Filter.filter(record):实现过滤功能,该方法在 logging 模块源文件中的 Filter 类,参数为 LogRecord 对象,通过比较日志级别以及一些选项来决定信息是否过滤。

Formatter 对象:

Formatter.format(record):根据 Formatter 对象的设置,格式化 LogRecord 对象,最终输出日志记录的完整字符串。

三、Python 日志库的使用案例

案例一:

一个简单的 Web 应用需要记录调试信息和报错信息:

import logging
from logging.handlers import RotatingFileHandler

# 初始化 logging 模块
logging.basicConfig(level=logging.INFO)

# 创建一个日志记录器实例
logger = logging.getLogger('mylogger')
# 创建一个 RotatingFileHandler,设置日志文件的名称和路径,以及日志文件大小限制和备份数量
handler = RotatingFileHandler('myapp.log', maxBytes=10*1024*1024, backupCount=3)
handler.setLevel(logging.INFO)
# 设置记录器的日志处理器为刚刚创建的 handler
logger.addHandler(handler)

# 记录日志信息
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')

上述代码定义了一个RotatingFileHandler,用于记录日志信息。这个Handler类中有一个可以设置日志大小,日志个数等信息的参数。当日志文件达到预定大小之后,就会被轮询保存,设定的个数就是取决于 backupCount 参数。

案例二:

一个 Web 服务器需要在控制台、文件和远程服务器上记录日志信息:

import logging
import logging.handlers
import socket

class LogstashFormatter(logging.Formatter):
    def format(self, record):
        # 将日志格式化为 json 序列化的格式
        record.message = record.getMessage()
        if isinstance(record.msg, dict):
            record.msg = json.dumps(record.msg)
        record.hostname = socket.gethostname()
        record.pid = os.getpid()
        record.level = record.levelname
        record.logger_name = record.name
        return super(LogstashFormatter, self).format(record)

# 创建 logger
logger = logging.getLogger('mylogger')
logger.setLevel(logging.DEBUG)

# 创建 handler,输出到控制台和文件
stream_handler = logging.StreamHandler()
file_handler = logging.handlers.RotatingFileHandler('myapp.log', maxBytes=10240, backupCount=3)
stream_handler.setLevel(logging.INFO)
file_handler.setLevel(logging.WARNING)

# 创建 remote handler,输出到远程服务器
log_server = '192.168.0.1'
remote_handler = logging.handlers.SocketHandler(log_server, logging.handlers.DEFAULT_TCP_LOGGING_PORT)

# Set formatter
formatter = LogstashFormatter("""{"hostname": "%(hostname)s", "pid": "%(process)d", "level": "%(levelname)s", "logger_name": "%(name)s", "message": %(message)s}""")
stream_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
remote_handler.setFormatter(formatter)

# 添加 handler
logger.addHandler(stream_handler)
logger.addHandler(file_handler)
logger.addHandler(remote_handler)

# 记录日志信息
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')

上述代码中定义了一个 LogstashFormatter 类,该类重载了日志的 format 方法,将日志序列化成为 JSON 格式并记录在日志文件中。同时,通过 socket handler 实现将日志输出到远程服务器的功能。

结语

通过 Python logging 模块,开发者可以方便地实现日志的记录和管理。针对不同的应用场景,灵活地选择日志记录器和 handler,可以实现日志的多样化输出。最后,使用 Python 日志模块不仅能够大大提高 Python 开发的效率,而且使得代码质量更好、更容易维护。