Python如何使用日志功能?代码示例教程

2021年11月16日19:37:26 发表评论 1,214 次浏览

Python如何使用日志?了解如何使用 Python 的内置日志记录模块来记录你的 Python 应用程序、更改默认格式、级别,并在具体示例中学习,以及使用日志记录处理程序。

日志记录允许程序员和软件开发人员跟踪在他们的软件中发生的事件,它不仅可以跟踪实际事件,还可以跟踪事件何时发生、在哪个函数中甚至在哪一行中。

日志记录会生成一组在你的应用程序中发生的详细事件。例如,如果你的应用程序中某处有错误,当你在代码中正确设置日志记录时,你可以轻松找到问题的原因。

如何使用Python中的日志功能?有用的日志不仅可以帮助我们调试错误,还可以为我们在尝试了解特定代码实际执行的操作时提供巨大帮助。在本教程中,你将学习如何使用Python 中的内置日志模块

你可能想知道,为什么我们不应该只使用已知print()函数?好吧,你应该只在小的 Python 脚本上使用它,但是对于更大的复杂程序,它很快就会变得混乱,你绝对应该使用日志记录。

日志记录是一种更清晰的方式来跟踪你的代码正在做什么。几乎每个生产级应用程序都使用这种技术来跟踪他们的应用程序正在经历的阶段。

日志模块

Python使用日志功能示例:Logging 模块内置于Python 标准库中,是 Python 程序员快速入门的强大即用型工具。这也是一种方便的方法,大多数第三方 Python 库都使用它。

Logging 模块自带 5 个标准日志级别,表示事件的严重程度,每个级别都有相应的方法可以用于记录该级别的事件,下表显示了所有日志级别及其数值以及我们何时使用它:

 等级 数值 使用时
 DEBUG 10 详细信息,例如尝试查找程序中的错误。
 INFO 20 确认一切按预期工作的信息性消息。
 WARNING 30 表示发生了意想不到的事情,告诉一些潜在的问题或弃用警告。
 ERROR 40 指定软件无法执行某些功能,但仍允许应用程序继续运行。
 CRITICAL 50 会导致程序停止运行的严重错误。 

Python如何使用日志?以下代码单元将所有级别的简单日志消息执行到控制台:

import logging

# make a debug message
logging.debug("This is a simple debug log")
# make an info message
logging.info("This is a simple info log")
# make a warning message
logging.warning("This is a simple warning log")
# make an error message
logging.error("This is a simple error log")
# make a critical message
logging.critical("This is a simple critical log")

输出:

WARNING:root:This is a simple warning log
ERROR:root:This is a simple error log
CRITICAL:root:This is a simple critical log

太棒了,所以默认的日志格式是级别、记录器的名称(默认为 root)和消息。在后面的部分中,我们将看到如何更改此格式以添加更多有用的信息。

如何使用Python中的日志功能?你可能会疑惑,为什么DEBUGINFO消息也登录不上去?嗯,这是因为默认的日志记录级别是WARNING

# just mapping logging level integers into strings for convenience
logging_levels = {
    logging.DEBUG: "DEBUG", # 10
    logging.INFO: "INFO", # 20
    logging.WARNING: "WARNING", # 30
    logging.ERROR: "ERROR", # 40
    logging.CRITICAL: "CRITICAL", # 50
}

# get the current logging level
print("Current logging level:", logging_levels.get(logging.root.level))

输出:

Current logging level: WARNING

因此,使用此级别,日志记录模块会记录级别为WARNING或以上的消息,唯一通过的消息是WARNING,ERRORCRITICAL。如果你将其设置为INFO,那么INFOWARNINGERRORCRITICAL消息将打通,等等。

以下代码行打印默认日志记录格式:

# get the current logging format
print("Current logging format:", logging.BASIC_FORMAT)

复制输出:

Current logging format: %(levelname)s:%(name)s:%(message)s

对,所以默认格式是级别名称、记录器名称和实际消息。

基本配置

Python使用日志功能示例:logging 模块为我们提供了一个有用的basicConfig()方法,它允许我们在日志记录过程中更改几个参数,它接受一堆有用的参数,以下是最常用的参数:

  • filename: 指定要登录的文件名,因此它将登录到文件而不是控制台。
  • filemode: 指定打开文件的模式,默认'a'为append、'w'to write等。
  • level:设置根记录电平到指定的电平,这是logging.DEBUGlogging.INFOlogging.WARNINGlogging.ERRORlogging.CRITICAL
  • format: 记录器的指定格式字符串。
  • datefmt:日期/日期时间的格式。
  • handlers: 如果指定,这应该是一个可迭代的日志处理程序,它将被添加到根处理程序中。

更改日志记录级别

你可以使用以下basicConfig()方法轻松更改严重性级别:

import logging

# make a basic logging configuration
# here we set the level of logging to DEBUG
logging.basicConfig(
    level=logging.DEBUG
)

# make a debug message
logging.debug("This is a simple debug log")
# make an info message
logging.info("This is a simple info log")
# make a warning message
logging.warning("This is a simple warning log")
# make an error message
logging.error("This is a simple error log")
# make a critical message
logging.critical("This is a simple critical log")

复制事实上,现在所有的消息都会通过:

DEBUG:root:This is a simple debug log
INFO:root:This is a simple info log        
WARNING:root:This is a simple warning log  
ERROR:root:This is a simple error log      
CRITICAL:root:This is a simple critical log

更改日志格式

Python如何使用日志?我们可以通过将 format 参数设置为basicConfig()method来更改日志记录格式:

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
)

logging.info("This is an info message!")

输出:

2020-10-10 19:26:19,908 - INFO - This is an info message!

如何使用Python中的日志功能?现在我们的日志消息中有日期时间。请注意,我们使用%(asctime)s属性来获取日期时间、%(levelname)s级别名称和%(message)s实际日志消息。

还有很多其他属性,这里是一些最重要的属性:

  • %(funcName)s:包含日志调用的函数的名称。
  • %(lineno)d:发出日志记录调用的源行号(如果可用)。
  • %(module)s: 模块名称。
  • %(name)s:用于记录调用的实际记录器的名称。
  • %(process)d:进程 ID(如果可用)。

请检查此链接以获取所有可用的LogRecord属性。

如果要更改日期格式,则还应该更改datefmt参数:

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    datefmt="[%Y-%m-%d] %H:%M:%S",
)

logging.info("This is an info message!")

time.strftime()time.strptime()方法的格式代码相同,请在此处获取列表。

输出:

[2020-10-10] 19:33:23 - INFO - This is an info message!

复制太棒了,现在让我们用一个例子来弄脏我们的手!

Python使用日志功能示例

Python如何使用日志?下面的秘籍是在 Python 中使用日志模块的一个很好的例子:

import logging
import math

logging.basicConfig(level=logging.DEBUG,
                    handlers=[logging.FileHandler('logs.log', 'a', 'utf-8')],
                    format="%(asctime)s %(levelname)-6s - %(funcName)-8s - %(filename)s - %(lineno)-3d - %(message)s",
                    datefmt="[%Y-%m-%d] %H:%M:%S - ",
                    )

logging.info("This is an info log")

def square_root(x):
    logging.debug(f"Getting the square root of {x}") 
    try:
        result = math.sqrt(x)
    except ValueError:
        logging.exception("Cannot get square root of a negative number")
        # or
        # logging.error("Cannot get square root of a negative number", exc_info=True)
        return None
    logging.info(f"The square root of {x} is {result:.5f}")
    return result

square_root(5)
square_root(-5)

在此示例中,我们使用 handlers 参数传递日志处理程序列表,我们指定FileHandlerlogs.log以追加模式和UTF-8编码记录到文件。

运行上述代码后,生成的logs.log文件如下:

[2020-10-10] 19:44:49 -  INFO   - <module> - logger_file.py - 10  - This is an info log
[2020-10-10] 19:44:49 -  DEBUG  - square_root - logger_file.py - 13  - Getting the square root of 5
[2020-10-10] 19:44:49 -  INFO   - square_root - logger_file.py - 21  - The square root of 5 is 2.23607
[2020-10-10] 19:44:49 -  DEBUG  - square_root - logger_file.py - 13  - Getting the square root of -5
[2020-10-10] 19:44:49 -  ERROR  - square_root - logger_file.py - 17  - Cannot get square root of a negative number
Traceback (most recent call last):
  File "c:/pythoncode-tutorials/python-standard-library/logging/logger_file.py", line 15, in square_root
    result = math.sqrt(x)
ValueError: math domain error

太棒了,我们指定了函数名称以及事件的行号,注意当日志记录不在函数中时,<module>标记将指示它在模块级别(不在任何函数中)。

square_root()我们使用的玩具函数是捕获ValueError每当我们传递负值时引发的 a,我们使用logging.exception()function 在日志文件中包含错误回溯,它与使用set 的logging.error()function相同。exc_infoTrue

使用处理程序

Python使用日志功能示例:到目前为止,我们一直在使用模块级别的日志记录,但是如果我们想为不同的目的使用多个记录器怎么办?这就是处理程序发挥作用的地方。

当我们想要配置我们自己的记录器并将日志发送到多个地方时,我们会使用日志处理程序。我们可以使用处理程序将日志消息发送到标准输出、文件,甚至通过 HTTP。

Python如何使用日志?以下示例使用logging.getLogger()方法检索记录器对象并向其附加处理程序:

import logging

# return a logger with the specified name & creating it if necessary
logger = logging.getLogger(__name__)

# create a logger handler, in this case: file handler
file_handler = logging.FileHandler("file.log")
# set the level of logging to INFO
file_handler.setLevel(logging.INFO)

# create a logger formatter
logging_format = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")

# add the format to the logger handler
file_handler.setFormatter(logging_format)

# add the handler to the logger
logger.addHandler(file_handler)

# use the logger as previously
logger.critical("This is a critical message!")

我们还为文件处理程序 usingsetFormatter()方法设置了一个格式化程序,这是file.log文件的输出:

2020-10-10 20:00:16,019 - CRITICAL - This is a critical message!

结论

如何使用Python中的日志功能?现在希望你开始在 Python 程序中使用日志记录而不是常规print()函数,我强烈建议你查看Python 文档中的教程以获取更深入的信息。

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: