您的位置:

Python 中的日志

在本教程中,我们将学习标准日志模块的基础知识。

什么是日志记录?

日志是标准库中的一个 Python 模块,它提供了与从 Python 程序中发布日志消息的框架一起工作的工具。日志用于跟踪软件运行时发生的事件。

开发人员在进行日志记录时广泛使用该模块。它是软件开发、运行和调试中非常重要的工具。

日志记录有利于日志记录的存储。假设没有日志记录,程序在执行过程中被中断,我们将无法找到问题的实际原因。

不知何故,我们发现了崩溃的原因,但解决这个问题需要花费大量时间。使用日志记录,我们可以留下痕迹,这样如果问题发生在程序中,我们就可以很容易地找到问题的原因。

在运行应用时,我们可能会面临许多问题,比如我们假设一个整数,我们被赋予了一个浮点数,服务正在维护中,等等。这些问题很难确定,也很耗时。

日志工作原理

日志是初学者和企业使用的强大模块。该模块提供了组织不同控制处理程序的能力,并向这些处理程序传输日志消息。

要发布日志消息,我们需要如下导入日志模块。


import logging 

现在,我们将调用记录器来记录我们想要看到的消息。日志模块提供了指定事件严重性的五个级别。每个事件都包含可用于记录严重级别事件的并行方法。让我们了解以下事件及其工作原理。

  1. DEBUG - 用于提供详细信息,只有在有诊断问题时才使用。
  2. INFO - 它提供了关于事物按照我们想要的方式工作的信息。
  3. WARNING - 用来警告意外发生的事情,否则我们将在即将到来的时间里面临问题。
  4. ERROR - 用来在我们遇到一些严重的麻烦时,通知软件还没有执行一些程序。
  5. CRITICAL - 指定严重错误,程序本身可能无法继续执行。

以上级别足以处理任何类型的问题。下面给出了这些相应的数值。

| 水平 | 数值 | | 紧急事件集 | Zero | | 调试 | Ten | | 信息 | Twenty | | 警告 | Thirty | | 错误 | Forty | | 批评的 | Fifty |

日志模块提供了许多功能。它由几个常量、类和方法组成。常数由后面的所有大写字母表示;这些类用大写字母表示。小写的项目代表方法。

让我们来看看模块本身提供的几个 logger 对象。

  • Logger.info(msg) : 用于在此 Logger 上记录级别为 info 的消息。
  • 记录器.警告(msg) : 用于在该记录器上记录警告级别的消息。
  • Logger.error(msg) : 用于在此 Logger 上记录级别为 error 的消息。
  • Logger.critical(msg) : 用于在此日志记录程序上记录级别为 critical 的消息。
  • Logger.log(lvl,msg) : 用于在这个 Logger 上记录一个整数级 lvl 的消息。
  • Logger.exception(msg) : 用于在此 Logger 上记录级别为 ERROR 的消息。
  • Logger.setLevel(lvl) : 用于将该 Logger 的开头设置为 lvl。它将忽略下面写的所有消息。
  • Logger . addfilter(filter):用于向该 logger 添加特定的筛选器。
  • Logger . remove filter(filter):用于为此 logger 消除特定的筛选器。
  • 记录器.过滤器(记录):它把记录器的过滤器放到记录上。如果记录可用并且要处理,则返回真。否则,它将返回 False。
  • Logger.addHandler(hdlr) : 用于将特定的处理程序 hdlr 添加到此记录器的中。
  • Logger . remove handler(hdlr):用于将特定的处理程序 hdlr 排除到该 logger。
  • Logger.hasHandlers() : 用于验证记录器是否包含任何已配置的处理程序。

让我们理解下面的例子。

示例-


import logging

logging.debug('The debug message is displaying')
logging.info('The info message is displaying')
logging.warning('The warning message is displaying')
logging.error('The error message is displaying')
logging.critical('The critical message is displaying')

输出:

WARNING:root:The warning message is displaying
ERROR:root:The error message is displaying
CRITICAL:root:The critical message is displaying 

说明:

正如我们在上面的输出中看到的,每条消息都与根一起显示,根是为其默认日志记录程序指定的日志记录模块名称。消息和级别名称用冒号(:)分隔,并以默认输出格式打印消息。

我们可以注意到 debug() 和 info() 消息没有显示消息,因为默认情况下,日志模块记录的消息的严重级别为 WARNING、ERROR 和 CRITICAL 。

基本配置

日志记录的主要任务是将记录的事件存储在文件中。日志模块提供基本配置(kwarg)** ,用于配置日志。

它接受一些常用的论点如下。

  • 级别- 指定的严重级别由根级别设置。
  • 文件名- 指定一个文件。
  • 文件模式- 以特定模式打开文件。打开文件的默认模式是 a,这意味着我们可以追加内容。
  • 格式- 格式定义日志消息的格式。

我们可以通过使用我们想要记录的级别参数来设置日志消息的级别。我们需要传递类中的一个常量,它将允许所有的日志调用。

让我们理解下面的例子。

示例-


import logging

logging.basicConfig(level=logging.DEBUG)
logging.debug('The dubug message is logged')

输出:


DEBUG:root: The debug will be get logged

同样,我们可以将消息记录到一个文件中,而不是显示在控制台上,文件名和文件模式可以用在基本配置()功能中,我们可以使用格式属性来决定消息的格式。让我们理解下面的例子。

示例-


import logging

logging.basicConfig(filename='msg.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s')
logging.warning('This will get logged to a file')

输出:


root - WARNING - This will get logged to a file

说明:

以上输出将显示在消息日志文件中,而不是控制台中。我们在 w 中打开了文件,这意味着文件是以“写模式”打开的。如果多次调用 basicConfig() ,那么程序的每次运行都会重写日志文件的输出。basiconfig()函数可以通过传递附加参数(https://docs . python . org/3/library/logging . html # logging . basiconfig)进行修改。

让我们理解下面的例子。

示例-


import logging

#Create and configure logger using the basicConfig() function
logging.basicConfig(filename="newfile.log",
               format='%(asctime)s %(message)s',
               filemode='w')

#Creating an object of the logging
logger=logging.getLogger()

#Setting the threshold of logger to DEBUG
logger.setLevel(logging.DEBUG)

#Test messages
logger.debug("This is a harmless debug Message")
logger.info("This is just an information")
logger.warning("It is a Warning. Please make changes")
logger.error("You are trying to divide by zero")
logger.critical("Internet is down") 

输出:

2020-09-05 13:17:39,204 This is a harmless debug Message
2020-09-05 13:17:39,205 This is just an information
2020-09-05 13:17:39,205 It is a Warning. Please make changes
2020-09-05 13:17:39,205 You are trying to divide by zero
2020-09-05 13:17:39,205 Internet is down

说明:

上面的代码将生成一个文件,我们可以在打开文件时看到输出。

格式化输出

程序中作为日志消息传递的字符串可以根据我们的要求进行修改。给定字符串和部分日志记录中有一些基本元素。让我们理解下面的例子。

示例-


import logging

logging.basicConfig(format='%(process)d-%(levelname)s-%(message)s')
logging.warning('This is a Warning Message')

输出:

18472-WARNING-This is a Warning Message

格式参数可以按照我们的要求接受任何形式的具有日志记录属性的字符串。

让我们理解下面的例子-

示例-


import logging

logging.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO)
logging.info('Admin logged in')

输出:

2020-09-02 20:12:06,288 - Admin logged in

% ASC time 属性增加了日志记录的创建时间。我们还可以使用 datefmt 属性自定义格式,它提供了与 datetime 模块相同的功能。

示例-


import logging

logging.basicConfig(format='%(asctime)s - %(message)s', datefmt='%d-%b-%y %H:%M:%S')
logging.warning('Admin logged out')

输出:

02-Sep-20 13:29:05 - Admin logged out

记录变量数据

有时,我们希望在日志中包含来自应用的动态信息。日志记录方法接受字符串作为参数,最好用变量数据格式化字符串并传递给日志方法。

但除此之外,我们还可以为消息使用格式字符串,并将变量数据作为参数追加。

让我们理解下面的例子-


import logging

name = 'Peter Decosta'

logging.error('%s raised an error', name)

输出:

ERROR:root: Peter Decosta raised an error

说明:

传递给该方法的参数将作为消息中的变量数据进行卷积。

我们可以使用 f{string}来格式化给定的字符串。它提供了一种简单快捷的方法来处理字符串。

示例-


import logging

name = 'Antonio Mino'

logging.error(f'{name} raised an error')

输出:

ERROR:root: Antonio Mino raised an error

捕获栈跟踪

我们可以使用日志模块在应用中捕获完整的跟踪栈。测井功能中有一个 exc_info 参数;如果设置为真,则可以捕获异常信息。

让我们理解下面的例子-

示例-


import logging

a = 10
b = 0

try:
  c = a / b
except Exception as e:
  logging.error("Exception occurred", exc_info=True)

输出:

ERROR:root:Exception occurred
Traceback (most recent call last):
  File "C:/Users/DEVANSH SHARMA/PycharmProjects/Hello/loggingFile.py", line 224, in <module>
    c = a / b
ZeroDivisionError: division by zero

说明:

如果我们不将 true 设置为 exc_info,输出将不会通知我们异常。如果一个错误只显示以下输出,那么很难在数千行代码中调试它。


ERROR:root:Exception occurred

还有其他选项可以获得关于异常的完整信息。日志模块提供异常()方法,记录一条带有 ERROR 的消息,并附上异常信息。要使用它,调用日志记录.异常()方法与调用日志记录.错误(exc_info = True) 相同。

让我们理解下面的例子。

示例-


import logging

a = 10
b = 0

try:
  c = a / b
except Exception as e:
  logging.exception("Exception occurred", exc_info=True)

输出:

ERROR:root:Exception occurred
Traceback (most recent call last):
  File "C:/Users/DEVANSH SHARMA/PycharmProjects/Hello/loggingFile.py", line 224, in <module>
    c = a / b
ZeroDivisionError: division by zero

我们可以使用 error()、debug()或 critical()方法中的任意一个选项来获取有关异常的信息。

类和函数

到目前为止,我们已经看到了名为根的默认记录器。无论何时调用其功能,如 logging.debug()、 logging.error()等,都会用到日志模块。我们也可以通过创建记录器类的对象来定义自己的记录器。这里,我们定义了常用的类和函数。

下面是日志模块中定义的类和函数。

  • 记录器- 记录器对象用于直接调用函数。
  • 日志记录- 它自动创建日志记录文件,该文件包含与被记录的所有事件相关的信息,如记录器的名称、功能、行号、消息等。
  • 处理程序- 处理程序用于将日志记录发送到输出端点。文件处理器、流处理器、HTTPHandler、SMTTPHandler 是处理器的子类。
  • 格式化程序- 格式化程序用于定义输出的结构。它使用字符串格式化方法来指定日志消息的格式。

如果我们没有要格式化的消息,默认情况下使用原始消息。默认格式日期格式是。


%Y-%m-%d %H:%M:%S

以下格式用于以人类可读的格式制作日志消息。


'%(asctime)s - %(levelname)s - %(message)s'

我们通常使用 Logger 类的对象,这些对象是使用 logging.getLogger(name) 函数创建的。如果用同一个名称多次调用 getLogger() 方法,将返回同一个 Logger 对象的引用。

让我们理解下面的例子:

示例-


import logging

logger = logging.getLogger('first_logger')
logger.warning('This is a warning message')

输出:

This is a warning message

说明:

我们已经创建了自己的记录器名称 first_logger ,但是与根记录器不同的是, first_logger 不是输出格式的一部分。要显示它,请将其传递给配置函数。那么输出将如下所示。


WARNING:first_logger:This is a warning message

使用处理程序

处理程序通常用于配置日志记录程序,并将日志一次传输到许多地方。它通过 HTTP 或电子邮件将日志消息发送到标准输出流或文件。

让我们理解以下创建处理程序的示例。

示例:


import logging

# Create a custom logger_obj
logger_obj = logging.getLogger(__name__)

# Create handlers
w_handler = logging.StreamHandler()
e_handler = logging.FileHandler('file.log')
w_handler.setLevel(logging.WARNING)
e_handler.setLevel(logging.ERROR)

# Create formatters and add it to handlers
c_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
f_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
w_handler.setFormatter(c_format)
e_handler.setFormatter(f_format)

# Add handlers to the logger_obj
logger_obj.addHandler(w_handler)
logger_obj.addHandler(e_handler)

logger_obj.warning('This is a warning message')
logger_obj.error('This is an error message')

输出:

__main__ - WARNING - This is a warning message
__main__ - ERROR - This is an error message

说明:

在下面的程序中,我们创建了一个名为 logger_obj 的自定义日志记录程序,并创建了一个日志记录程序来存储日志事件的所有记录,并将其传递给它拥有的所有处理程序: w_handlers 和 e_handlers 。

w_handlers 是一个级别为“警告”的流处理程序。它接受来自日志记录的日志,以格式字符串生成输出,并将其打印到屏幕上。

e_handler 是一个文件处理程序,级别为错误。它将日志记录忽略为其警告级别。

结论

日志模块灵活易用。这对于跟踪日志记录和向用户显示适当的消息非常有用。它提供了创建自定义日志级别、处理程序类和许多其他有用方法的灵活性。

它还为小型项目提供基本的日志记录。

在本教程中,我们已经讨论了日志模块的所有基本概念。我们已经介绍了不同级别的生成消息。