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技术站