1. Logging 模块介绍
使用标准库模块提供的日志记录 API
的主要好处是所有 Python
模块都可以参与日志记录,因此您的应用程序日志可以包含您自己的消息与来自第三方模块的消息集成。The key benefit of having the logging API provided by a standard library module is that all Python modules can participate in logging, so your application log can include your own messages integrated with messages from third-party modules.
下面列出了该模块定义的基本类及其功能。The basic classes defined by the module, together with their functions, are listed below.
- 记录器公开应用程序代码直接使用的接口。Loggers expose the interface that application code directly uses.
- 处理器将日志记录(由记录器创建)发送到适当的目的地。 send the log records (created by loggers) to the appropriate destination.
- 过滤器提供了更细粒度的工具来确定要输出哪些日志记录。Filters provide a finer grained facility for determining which log records to output.
- 格式器指定最终输出中日志记录的布局。Formatters specify the layout of log records in the final output.
2. 日志级别 Logging Levels
Level | Numeric value | Describe |
---|---|---|
CRITICAL | 50 | 当发生严重错误,导致应用程序不能继续运行时记录的信息 |
ERROR | 40 | 由于一个更严重的问题导致某些功能不能正常运行时记录的信息 |
WARNING | 30 | 当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的 |
INFO | 20 | 信息详细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工作 |
DEBUG | 10 | 最详细的日志信息,典型应用场景是 问题诊断 |
logging
默认的日志级别为 warning
。
程序
import logging
logging.debug("debug_msg")
logging.info("info_msg")
logging.warning("warning_msg")
logging.error("error_msg")
logging.critical("critical_msg")
输出
WARNING:root:warning_msg
ERROR:root:error_msg
CRITICAL:root:critical_msg
3. 配置方式
a. basicConfig
(不推荐)
Does basic configuration for the logging system by creating a StreamHandler
with a default Formatter
and adding it to the root logger. The functions debug()
, info()
, warning()
, error()
and critical()
will call basicConfig()
automatically if no handlers are defined for the root logger.
如果root logger
已经配置了handlers
,则此函数不执行任何操作,除非关键字参数force
设置为True
。This function does nothing if the root logger already has handlers configured, unless the keyword argument force is set to True
.
Format | Description |
---|---|
filename | 使用指定的文件名创建创建FileHandler (默认使用StreamHandler )。 Specifies that a FileHandler be created, using the specified filename, rather than a StreamHandler . |
filemode | 如果指定了filename,则以这种filemode打开文件(默认为'a' )。 If filename is specified, open the file in this mode. Defaults to 'a' . |
format | 为handler 指定的格式字符串。 Use the specified format string for the handler. Defaults to attributes levelname , name and message separated by colons. |
datefmt | 指定日期/时间格式。 Use the specified date/time format, as accepted by time.strftime() . |
level | 指定日志级别。 Set the root logger level to the specified level. |
stream | 使用指定的stream 来初始化 StreamHandler 。 Use the specified stream to initialize the StreamHandler . Note that this argument is incompatible with filename - if both are present, a ValueError is raised. |
handlers | 指定handler 。If specified, this should be an iterable of already created handlers to add to the root logger. Any handlers which don’t already have a formatter set will be assigned the default formatter created in this function. Note that this argument is incompatible with filename or stream - if both are present, a ValueError is raised. |
force | 如果将此关键字参数指定为 true,则在执行其他参数指定的配置之前,将删除并关闭任何附加到根记录器的现有handler 。If this keyword argument is specified as true, any existing handlers attached to the root logger are removed and closed, before carrying out the configuration as specified by the other arguments. |
其中,format 包含以下常用属性:
Format | Description |
---|---|
%(asctime)s | Human-readable time when the LogRecord was created. By default this is of the form ‘2003-07-08 16:49:45,896’ (the numbers after the comma are millisecond portion of the time). |
%(filename)s | Filename portion of pathname . |
%(levelname)s | Text logging level for the message ('DEBUG' , 'INFO' , 'WARNING' , 'ERROR' , 'CRITICAL' ). |
%(lineno)d | Source line number where the logging call was issued (if available). |
%(message)s | The logged message, computed as msg % args . This is set when Formatter.format() is invoked. |
%(name)s | Name of the logger used to log the call. |
%(pathname)s | Full pathname of the source file where the logging call was issued (if available). |
示例 1 (format
的使用)
程序
import logging
logging.basicConfig(format="%(asctime)s | %(levelname)-8s | %(filename)8s:%(lineno)-3s | %(message)s",
level=logging.DEBUG)
logging.debug("debug_msg")
logging.info("info_msg")
logging.warning("warning_msg")
logging.error("error_msg")
logging.critical("critical_msg")
输出
2022-06-01 09:53:38,618 | DEBUG | main.py:5 | debug_msg
2022-06-01 09:53:38,619 | INFO | main.py:6 | info_msg
2022-06-01 09:53:38,619 | WARNING | main.py:7 | warning_msg
2022-06-01 09:53:38,619 | ERROR | main.py:8 | error_msg
2022-06-01 09:53:38,619 | CRITICAL | main.py:9 | critical_msg
示例 2 (datefmt
的使用)
程序
import logging
logging.basicConfig(format="%(asctime)s | %(levelname)-8s | %(filename)8s:%(lineno)-3s | %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
level=logging.DEBUG)
logging.debug("debug_msg")
logging.info("info_msg")
logging.warning("warning_msg")
logging.error("error_msg")
logging.critical("critical_msg")
输出
2022-06-01 09:55:55 | DEBUG | main.py:6 | debug_msg
2022-06-01 09:55:55 | INFO | main.py:7 | info_msg
2022-06-01 09:55:55 | WARNING | main.py:8 | warning_msg
2022-06-01 09:55:55 | ERROR | main.py:9 | error_msg
2022-06-01 09:55:55 | CRITICAL | main.py:10 | critical_msg
b. 代码配置
(不推荐)
组件名称 | 对应类名 | 功能描述 |
---|---|---|
日志器 | Logger | 公开应用程序代码直接使用的接口Loggers expose the interface that application code directly uses. |
处理器 | Handler | 将日志记录(由记录器创建)发送到适当的目的地。 send the log records (created by loggers) to the appropriate destination. |
过滤器 | Filter | 提供了更细粒度的工具来确定要输出哪些日志记录。Filters provide a finer grained facility for determining which log records to output. |
格式器 | Formatter | 指定最终输出中日志记录的布局Formatters specify the layout of log records in the final output. |
Logger
常用的配置方法:
方法 | 描述 |
---|---|
Logger.setLevel() | 设置日志器将会处理的日志消息的最低日志级别 |
Logger.addHandler() | 为该logger对象添加一个handler对象 |
Logger.addFilter() | 为该logger对象添加一个filter对象 |
相较于BasicConfig
,logging.getLogger
可以更灵活的进行配置。Although there is a default logger, we usually want to make and use other loggers that can be configured separately. This is because we may want a different severity level or format for different loggers. A new logger can be created with:
logger = logging.getLogger("logger_name")
logger
具有parent
和child
的特性。Internally, the loggers are organized in a hierarchy. A logger created with:
logger = logging.getLogger("parent.child")
will be a child logger created under the logger with the name “parent
,” which, in turn, is under the root logger. Using a dot in the string signifies that the child logger is a child of the parent logger. In the above case, a logger with the name “parent.child
” is created as well as one with the name "parent"
implicitly.
在创建子记录器时,子记录器具有父记录器的所有属性,直到重新配置为止。Upon creation, a child logger has all the properties of its parent logger until reconfigured. We can demonstrate this with the following example:
示例 1
程序
import logging
# Create `parent.child` logger
logger = logging.getLogger("parent.child")
# Emit a log message of level INFO, by default this is not print to the screen
logger.info("this is info level")
logger.warning("this is warning level")
# Create `parent` logger
parentlogger = logging.getLogger("parent")
# Set parent's level to INFO and assign a new handler
handler = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s : %(name)s : %(levelname)s : %(message)s")
handler.setFormatter(formatter)
parentlogger.setLevel(logging.INFO)
parentlogger.addHandler(handler)
# Let child logger emit a log message again
logger.info("this is info level again")
输出
this is warning level
2022-06-01 10:16:16,937 : parent.child : INFO : this is info level again
c. fileConfig
(推荐)
配置文件
[loggers]
keys=root,mylog
[handlers]
keys=fileHandler, consoleHandler, smtpHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_mylog]
level=DEBUG
handlers=fileHandler, consoleHandler, smtpHandler
qualname=mylog
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[handler_fileHandler]
class=FileHandler
level=DEBUG
formatter=simpleFormatter
args=('python.log', 'w')
[handler_smtpHandler]
class=handlers.SMTPHandler
level=DEBUG
formatter=simpleFormatter
args=(("smtp.163.com", 25), "166******23@163.com", ["56****87@qq.com", "87*****21@qq.com"], 'Logger Subject', ("166******23@163.com", "NOMFDG*****Y"))
kwargs={'timeout': 10.0}
[formatter_simpleFormatter]
format=%(asctime)s | %(levelname)8s | %(filename)10s:%(lineno)-3d | %(message)s
import logging
import logging.config
logging.config.fileConfig('log_config.conf')
logger = logging.getLogger('mylog')
d. dictConfig
(推荐)
暂时没有总结,灵活性比fileConfig
更高。
# !/usr/bin/env python
# -*- coding:utf-8 -*-
'''
@CreateTime : 2020/12/29 14:08
@Author : shouke
@Shource : https://cloud.tencent.com/developer/article/1772559
'''
import logging
import logging.config
LOGGING_CONFIG = {
"version": 1,
"formatters": {
"default": {
'format': '%(asctime)s %(filename)s %(lineno)s %(levelname)s %(message)s',
},
"plain": {
"format": "%(message)s",
},
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "INFO",
"formatter": "default",
},
"console_plain": {
"class": "logging.StreamHandler",
"level": logging.INFO,
"formatter": "plain"
},
"file": {
"class": "logging.FileHandler",
"level": 20,
"filename": "./log.txt",
"formatter": "default",
}
},
"loggers": {
"console_logger": {
"handlers": ["console"],
"level": "INFO",
"propagate": False,
},
"console_plain_logger": {
"handlers": ["console_plain"],
"level": "DEBUG",
"propagate": False,
},
"file_logger": {
"handlers": ["file"],
"level": "INFO",
"propagate": False,
}
},
"disable_existing_loggers": True,
}
# 运行测试
logging.config.dictConfig(LOGGING_CONFIG)
logger = logging.getLogger("console_logger")
logger.debug('debug message')
logger.info('info message')
logger.warning('warning message')
logger.error('error message')
logger.critical('critical message')
参考资料:
[1] https://docs.python.org/3/library/logging.html
[2] https://machinelearningmastery.com/logging-in-python/
[3] https://www.cnblogs.com/yyds/p/6901864.html
[4] https://www.cnblogs.com/kangshuaibo/p/14700833.html
[5] https://www.bilibili.com/video/BV1sK4y1x7e1
[6] https://docs.python.org/3/library/logging.config.html