一文掌握Python日志系统(logging)

VOL.11390 views

1

Mar. 2024

写在前面

在使用任何编程语言时,最终目标都构建一个按照t特定指令正常运行的程序。然而,实际情况是很少能在一次尝试中达到期望的结果,您可能需要分析运行结果以确定错误。在现代软件中,了解运行时行为已成为标准实践,这就需要用到日志记录。

在本文中,我们将重点介绍 Python 的logging库的基础知识,该库提供了日志所有必要的功能,且易于使用。虽然,现在你可能正在使用 print 函数进行调试,但在生产环境中,按照日志记录标准工作非常重要。loging库正是为此而设计的。

日志记录的级别

简单来时,你可以选择所需的级别来控制需要输出的日志记录消息。日志记录库为每个级别提供单独的模块,它们从10到50进行编号。所有级别都是易于理解的。我们简单介绍一下这几个级别。

  • 调试(Debug):此日志级别主要用于调试,在生产环境中没有用处。它的日志级别为10。
  • 信息(Info):此日志级别提供了预期从程序行为中获得的信息。它的日志级别为20。
  • 警告(Warning):此日志级别通知用户发生了意外事件,但不严重,不会让程序停止。它的日志级别为30。
  • 错误(Error):此日志级别用于报告运行时的意外故障。它的日志级别为40。
  • 严重(Critical):此日志级别表示严重错误,可能导致应用程序停止运行。它的日志级别为50。

如何使用

以下是一个最简单的使用logging库的demo。在 basicConfig 中,我们提供了所需的日志记录级别。结果只有高于此级别的消息才会出现在输出中(包括当前级别)。因此,当我们想要查看 WARNING 级别的消息时,程序不会记录DEBUG和INFO级别的消息。

import logging

def test_logging():
 # 这里level确定了只会输出WARNING、ERROR、CRITICAL
 logging.basicConfig(level=logging.WARNING)

 logging.debug("DEBUG")
 logging.info("INFO")
 logging.warning("WARNING")
 logging.error("ERROR")
 logging.critical("CRITICAL")
test_logging()

输出:

WARNING:root:WARNING
ERROR:root:ERROR
CRITICAL:root:CRITICAL

更改基本配置

上面我们只是更改了配置中的 level 来确定输出的日志级别,其他设置均为默认。在这种情况下日志信息会直接打印到控制台。那么如果我们想要将日志记录到文件中,使用特定的时间格式那应该怎么做呢?下面是一段代码示例,该示例输出 ERROR 以上的日志,特定的格式并在最后存入到basic.log文件中。

import logging

def test_logging():
    logging.basicConfig(
        level=logging.ERROR,
        format="%(asctime)s | %(levelname)s | %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S",
        filename="basic.log")

    logging.debug("DEBUG")
    logging.info("INFO")
    logging.warning("WARNING")
    logging.error("ERROR")
    logging.critical("CRITICAL")

test_logging()

输出:

#2023-11-18 14:52:30 | ERROR | ERROR
#2023-11-18 14:52:30 | CRITICAL | CRITICAL

新的日志格式信息量更丰富,也提供了标准的时间格式方便阅读。这里我们不仅仅做了日期格式的改变,同时还指定了存储日志的文件。这也为后期日志的保存和分析做好了准备。

在准备投入生产的应用程序中,也可能会使用特定的存储系统,以支持弹性分析方法。此外,可以在日志消息中使用变量,但重要的是要谨慎,不要提供任何敏感信息,以避免未来通过日志泄露。

import logging

def test_logging():
    logging.basicConfig(
        level=logging.INFO,
        format="%(message)s")

    for i in ["Dog", "Cat"]:
        logging.info("%s is your animal!", i)

test_logging()

输出

# Dog is your animal!
# Cat is your animal!

自定义记录器

在前面的代码示例中,我们直接从库中调用了记录器。然而,我们也可以创建自定义对象并根据需要进行自定义。这种技术在某些情况下非常有用,了解如何实现它很重要。

例如,在下面的示例中,我们创建了一个名为 Test 的记录器,并将其日志级别设置为 DEBUG。然而,仅仅设置日志级别是不足以输出日志消息的,我们还需要使用处理器(handler)来实现。处理器本质上是将日志发送到特定目的地的对象。在这种情况下,我们将消息打印到控制台,但在生产环境中,通常会将所有消息发送到特殊的存储或数据库。

import logging

logger = logging.getLogger('TEST')
logger.setLevel(logging.DEBUG)

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

logger.debug("DEBUG")
logger.info("INFO")

输出:

# 2023-11-18 15:47:41,035 - TEST - DEBUG - DEBUG
# 2023-11-18 15:47:41,035 - TEST - INFO - INFO

我们添加了特定的格式并在处理器中使用它。这个简单的示例显示,可以创建多个记录器和处理器实例,并根据需要将相关日志发送到每个目的地。

总结

Python 的logging库是一种强大且灵活的工具,可帮助您进行调试、错误报告和问题排查。在开发和生产环境中,使用适当的日志记录级别和格式可以提供有关程序行为的详细信息,并有助于解决问题。您可以根据需要自定义日志记录的级别、格式和目标。希望这个简单的指南能够帮助您开始使用 Python 的日志记录库。