代码解析python标准库logging模块

1. 简介

logging是Python标准库中提供的一个标准日志工具模块,其主要的作用是用来记录应用程序的运行时信息。通过使用logging来输出日志可以更加方便的进行开发、调试、测试以及发布运行等的工作。

2. logging模块的基础用法

2.1 创建Logger对象

创建Logger对象是logging模块的第一步,Logger对象主要用于向后端输出日志信息,可以设置日志的级别、输出格式等相关信息,例如:

import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

其中,__name__参数是用来设置该Logger对象的名称,对于不同的模块和函数,Logger名称也可以不同,从而可以根据名称对不同的模块进行区分。

2.2 创建处理器(Handler)对象

同样可以通过设置不同的Handler对象来将日志输出到不同的地方,例如输出到控制台、文件、网络等等,常见的Handler类型有:StreamHandler、FileHandler、NetworkHandler等等。例如:

console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)

其中,我们创建了一个名为console_handler的StreamHandler对象,将其设置日志级别为DEBUG。

2.3 设置Formatter对象

Formatter对象用于设置日志格式,例如我们需要以这样的格式输出日志:"时间-模块名称-日志级别-日志内容",可以通过以下形式去创建这样一个Formatter对象:

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

其中,%(asctime)s用于表示时间信息,%(name)s用于表示模块名称,%(levelname)s用于表示日志级别,%(message)s用于表示日志内容。

2.4 将Handler添加到Logger对象上

一旦我们创建好了Logger对象、Handler对象和Formatter对象,就可以将它们组合起来,将日志信息输出到不同的地方了。例如,我们可以将一个StreamHandler添加到Logger对象上,以输出到控制台:

console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)

2.5 输出日志

最后,我们就可以在代码中像这样输出日志信息了:

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')

这样就可以将不同级别(DEBUG、INFO、WARNING、ERROR和CRITICAL)的日志信息输出到控制台(或其他Handler)上了。

3. logging模块的进阶用法

3.1 日志信息的存储和分级

用logging模块,我们可以在控制台把程序运行过程中的信息输出,但这些信息并不能作为程序的正式日志文件,因此需要将日志信息记录到文件中。

import logging

logger = logging.getLogger(__name__)
logger.setLevel(level=logging.INFO)

handler = logging.FileHandler("output.log")
handler.setLevel(level=logging.INFO)

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

logger.addHandler(handler)

logger.info("Start reading database")
# read database here
records = {"john": 55, "tom": 66}
logger.debug("Records: %s", records)
logger.info("Update records...")
# update records here
logger.info("Finish updating records")

以上代码,正常情况下是没有触发任何warning或error信息的,因此只有INFO级别的日志信息会被输出到控制台和日志文件中。

3.2 日志信息的格式化

格式化指输出内容的控制,可以输出文件名,行号,函数名等等。

例如,我们要将输出内容加上上下文信息,使得日志输出层次更加清晰,可以使用logger自带的Adapter方法,代码如下:

import logging

logger = logging.getLogger()

class ContextFilter(logging.Filter):
    """
    This is a filter which injects contextual information into the log.
    """

    def filter(self, record):
        # Adds context to the log record
        record.context = "Context information"
        return True


class ContextAdapter(logging.LoggerAdapter):
    """
    This adapter adds extra context information to the log messages.
    """
    def process(self, msg, kwargs):
        """
        Override LoggerAdapter's process function to add contextual info.
        """
        return '[%s] %s' % (self.extra['context'], msg), kwargs

def main():
    """
    Test logger
    """
    logger.addFilter(ContextFilter())
    logger.setLevel(logging.DEBUG)
    logger.info('Program started')
    adapter = ContextAdapter(logger, {'context': 'Extra Context'})
    adapter.debug('Debug event')
    adapter.warning('Warning event')
    adapter.error('Error event')
    logger.info('Program terminated')


if __name__ == '__main__':
    main()

输出内容将会是:

[2022-03-14 18:48:23,451] [INFO] [__main__] [11] Program started
[2022-03-14 18:48:23,451] [DEBUG] [__main__] [33] [Extra Context] Debug event
[2022-03-14 18:48:23,451] [WARNING] [__main__] [34] [Extra Context] Warning event
[2022-03-14 18:48:23,451] [ERROR] [__main__] [35] [Extra Context] Error event
[2022-03-14 18:48:23,451] [INFO] [__main__] [37] Program terminated

示例解析

示例1 配置logging模块

在本示例中,我们将Logger的日志级别设为DEBUG级别,输出的Handler设为console_handler以便输出到控制台,而formatter则是为了定义输出日志的格式。

import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)

logger.addHandler(console_handler)

在以上的代码中,我们使用了一个长度为5的日志级别,分别是:
* DEBUG:详细程度从低到高依次是NOTSET、DEBUG、INFO、WARNING、ERROR和CRITICAL。
* INFO:输出程序运行的一些一般性信息。
* WARNING:表示某些意外发生,或者不准备马上解决,但是在发生问题后仍能继续工作。
* ERROR:表示非常严重的问题,包括程序中的错误和异常以及其他不同寻常的情况。
* CRITICAL:表示严重错误,严重到系统无法继续运行的程度。

示例2 测试日志信息含上下文信息

该示例主要通过创建ContextFilter和ContextAdapter这两个类来定制化过滤器和适配器,为日志信息加上了上下文信息。

import logging

logger = logging.getLogger()

class ContextFilter(logging.Filter):
    """
    This is a filter which injects contextual information into the log.
    """

    def filter(self, record):
        # Adds context to the log record
        record.context = "Context information"
        return True


class ContextAdapter(logging.LoggerAdapter):
    """
    This adapter adds extra context information to the log messages.
    """
    def process(self, msg, kwargs):
        """
        Override LoggerAdapter's process function to add contextual info.
        """
        return '[%s] %s' % (self.extra['context'], msg), kwargs

def main():
    """
    Test logger
    """
    logger.addFilter(ContextFilter())
    logger.setLevel(logging.DEBUG)
    logger.info('Program started')
    adapter = ContextAdapter(logger, {'context': 'Extra Context'})
    adapter.debug('Debug event')
    adapter.warning('Warning event')
    adapter.error('Error event')
    logger.info('Program terminated')


if __name__ == '__main__':
    main()

在运行该示例后,我们可以看到日志的格式变为:

[2022-03-15 17:06:43,857] [INFO] [__main__] [11] Program started
[2022-03-15 17:06:43,857] [DEBUG] [__main__] [33] [Extra Context] Debug event
[2022-03-15 17:06:43,857] [WARNING] [__main__] [34] [Extra Context] Warning event
[2022-03-15 17:06:43,857] [ERROR] [__main__] [35] [Extra Context] Error event
[2022-03-15 17:06:43,857] [INFO] [__main__] [37] Program terminated

可以发现,已经在日志信息添加了上下文信息,并在内容前面加以了区分,方便开发者阅读和排查问题。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:代码解析python标准库logging模块 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • Python用20行代码实现完整邮件功能

    下面我将为你详细讲解“Python用20行代码实现完整邮件功能”的完整攻略。 首先,我们需要明确一下,要实现完整邮件功能所需要用到的模块是smtplib和email。smtplib模块是发送邮件的核心,而email模块则是生成邮件内容的核心。 接下来,我们先来看一下如何使用smtplib模块来发送邮件。以下是一个常规的邮件发送代码段: import smtp…

    python 2023年6月3日
    00
  • 无法通过 Homebrew 安装 Python 2.7.3 在 OSX Lion 上导入 wxPython

    【问题标题】:Can’t import wxPython on OSX Lion with Python 2.7.3 installed via Homebrew无法通过 Homebrew 安装 Python 2.7.3 在 OSX Lion 上导入 wxPython 【发布时间】:2023-04-06 14:40:01 【问题描述】: 从这个包http:/…

    Python开发 2023年4月7日
    00
  • python开发之基于thread线程搜索本地文件的方法

    下面为您详细讲解基于thread线程搜索本地文件的方法的完整攻略。 Python开发之基于thread线程搜索本地文件的方法 一、背景 在实际工作中,我们经常需要搜索本地文件,例如查找某个文件夹下所有的图片文件,或者查找包含某个关键字的文本文件等。当需要搜索的文件数量较多时,使用单线程进行搜索效率会较慢,而使用多线程可以大大提升搜索效率。 二、基于threa…

    python 2023年5月19日
    00
  • Python accumulate()计算汇总值

    针对Python中的accumulate()函数计算汇总值,我可以给出如下的完整攻略(包括介绍、使用方法、示例说明等): 介绍 accumulate()是Python标准库中itertools模块提供的一个函数,用于对一个可迭代对象(比如列表、元组等)进行累加计算,返回一个包含所有结果的可迭代对象。该函数接受两个参数:一个可迭代对象iterable和一个可选…

    python-answer 2023年3月25日
    00
  • Python入门_浅谈数据结构的4种基本类型

    Python入门_浅谈数据结构的4种基本类型 在使用Python进行编程时,了解数据结构的基本类型是非常重要的。 Python语言支持以下四种基本类型: 列表(List) 元组(Tuple) 集合(Set) 字典(Dictionary) 列表(List) 定义: 列表是Python中最基本的数据结构之一,可以作为一个有序的序列,内容可以包含不同类型的元素。 …

    python 2023年5月14日
    00
  • 利用Python list列表修改元素

    以下是详细讲解“利用Python list列表修改元素”的完整攻略。 在Python中,列表是一种常用的数据类型,它可以存储多个值支持各种操作。本文将详细讲解如何利用Python list列表修改元素,并提供两个示例说明。 修改元素 list列表中的元素可以通过索引进行修改。例如: lst = [1, 2, 3] lst[1] = 4 print(lst) …

    python 2023年5月13日
    00
  • python爬虫中抓取指数的实例讲解

    下面我将详细讲解“python爬虫中抓取指数的实例讲解”的完整攻略。 简介 在爬取网站数据时,有些站点会提供一些指数数据,比如搜索指数、热度指数等等。本文将介绍如何使用Python爬虫抓取这些指数数据。 步骤 本文将分为以下几步来讲解如何抓取指数数据: 确定目标网站和要抓取的指数数据 分析目标网站的请求方式和网页结构 使用Python的requests库发送…

    python 2023年5月14日
    00
  • python正则实现计算器功能

    Python正则表达式可以用来匹配字符串中的某种格式,对于计算器而言,就可以利用正则表达式实现输入的字符串转化为计算结果的功能。 步骤如下: 将输入的字符串中的空格去除掉 代码块: input_str = input_str.replace(‘ ‘, ”) 这一步很重要,可以去除多余的空格,避免对后续的计算造成影响。 利用正则表达式匹配数字和运算符 我们可…

    python 2023年6月3日
    00
合作推广
合作推广
分享本页
返回顶部