logging模块简介
Python的logging模块是一个非常强大的工具,用于在应用程序中记录和管理日志信息。它提供了灵活的功能,可以在不同的输出目标(如控制台、文件、网络等)中记录日志,并支持不同的日志级别。先前基于PEP 282 — A Logging System翻译了一篇Python 日志模块logging的使用,感觉文绉绉的,让人看不懂,所以重新进行了一次梳理。
核心概念
- Logger(记录器):Logger对象是应用程序可以直接使用的接口。你可以通过getLogger(name)获取一个记录器。通常,记录器会按照模块或类的名称进行命名,以便于区分不同的日志来源。
- Handler(处理器):Handler用于定义日志消息发送到的位置。常见的处理器有StreamHandler(用于输出到控制台)和FileHandler(用于输出到文件)。每个记录器可以附加多个处理器。
- Formatter(格式化器):Formatter用于定义日志消息的最终输出格式。你可以指定时间、日志级别、消息等的格式。通过设置格式化器,可以使日志输出更具可读性。
- Level(级别):日志级别用于指示日志消息的严重性。常用的日志级别有:
- NOTSET:未设置,默认值,不会记录任何消息。
- DEBUG:详细的信息,通常只在诊断问题时使用。
- INFO:确认程序按预期运行。
- WARNING:表示潜在的问题。
- ERROR:由于更严重的问题,程序已不能执行一些功能。
- CRITICAL:严重错误,程序可能无法继续运行。
基本用法
以下是一个简单的使用示例:
import logging # 创建一个logger logger = logging.getLogger('example_logger') logger.setLevel(logging.DEBUG) # 设置最低日志级别 # 创建一个handler,用于写入日志文件 file_handler = logging.FileHandler('example.log') file_handler.setLevel(logging.DEBUG) # 创建一个handler,用于输出到控制台 console_handler = logging.StreamHandler() console_handler.setLevel(logging.INFO) # 创建一个格式化器,并设置给处理器 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') file_handler.setFormatter(formatter) console_handler.setFormatter(formatter) # 给logger添加handler logger.addHandler(file_handler) logger.addHandler(console_handler) # 使用logger记录日志 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')
高级功能
- 配置日志:可以通过配置文件(如INI格式)或字典(如JSON格式)进行复杂的日志配置,使用config模块来加载这些配置。
- 日志的层次结构:Logger对象是分层次的,根记录器是所有日志的祖先。子记录器会继承父记录器的设置。
- 日志过滤:通过Filter对象可以实现更复杂的日志过滤机制,允许或拒绝特定的日志记录。
- 线程安全:logging模块是线程安全的,适合多线程应用程序使用。
- 性能:使用logging比直接使用print语句要高效,尤其是在大型应用程序中,因其可以动态调整日志级别,减少不必要的I/O操作。
通过灵活的配置和使用,Python的logging模块可以很好地满足各种应用程序的日志记录需求,从简单的调试到复杂的生产环境日志管理。
logging模块详解
Logger
功能:核心组件,用于记录日志消息。每个 Logger 对象对应一个日志记录器。
常用方法:
- getLogger(name):获取指定名称的 Logger 对象。如果 Logger 对象不存在,则创建一个新的。
- debug(msg, *args, **kwargs):记录调试级别的日志消息。
- info(msg, *args, **kwargs):记录信息级别的日志消息。
- warning(msg, *args, **kwargs):记录警告级别的日志消息。
- error(msg, *args, **kwargs):记录错误级别的日志消息。
- exception(msg, *args, **kwargs):记录异常级别的日志消息(包含异常信息)。
- critical(msg, *args, **kwargs):记录严重错误级别的日志消息。
- setLevel(level):设置 Logger 对象的日志级别。
- addHandler(handler):添加日志处理器。
- removeHandler(handler):移除日志处理器。
示例:
import logging logger = logging.getLogger('my_logger') logger.setLevel(logging.DEBUG) 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')
Handler
功能:处理日志消息并决定如何将其输出到不同的目标(例如控制台、文件、网络)。
常用处理器:
- StreamHandler:将日志消息输出到流(如stdout 或 sys.stderr)。
- FileHandler:将日志消息写入文件。
- RotatingFileHandler:将日志消息写入文件,并在文件达到指定大小时轮换。
- TimedRotatingFileHandler:根据时间间隔轮换日志文件。
- SocketHandler:将日志消息发送到网络套接字。
- SMTPHandler:通过电子邮件发送日志消息。
- HTTPHandler:通过 HTTP 请求发送日志消息。
示例:
import logging # Create a logger logger = logging.getLogger('my_logger') logger.setLevel(logging.DEBUG) # Create a console handler console_handler = logging.StreamHandler() console_handler.setLevel(logging.INFO) # Create a file handler file_handler = logging.FileHandler('app.log') file_handler.setLevel(logging.DEBUG) # Add handlers to logger logger.addHandler(console_handler) logger.addHandler(file_handler) logger.debug('Debug message') logger.info('Info message')
Formatter
功能:定义日志消息的格式,包括时间戳、日志级别、消息内容等。
常用格式化选项:
- ‘%(asctime)s’:时间戳。
- ‘%(name)s’:Logger 名称。
- ‘%(levelname)s’:日志级别名称。
- ‘%(message)s’:日志消息内容。
示例:
import logging logger = logging.getLogger('my_logger') logger.setLevel(logging.DEBUG) # Create a console handler handler = logging.StreamHandler() # Create a formatter formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) # Add handler to logger logger.addHandler(handler) logger.info('This is an info message')
Filter
功能:过滤不需要的日志消息,仅记录符合特定条件的消息。
常用方法:
- addFilter(filter):添加过滤器。
- removeFilter(filter):移除过滤器。
示例:
import logging class CustomFilter(logging.Filter): def filter(self, record): return 'important' in record.getMessage() logger = logging.getLogger('my_logger') logger.setLevel(logging.DEBUG) handler = logging.StreamHandler() handler.setFilter(CustomFilter()) logger.addHandler(handler) logger.debug('This is an important message') logger.debug('This is not important')
logging使用教程
基本用法
导入模块
首先,需要导入 logging 模块:
import logging
基本配置
可以使用 logging.basicConfig() 方法进行基本配置:
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
- level:设置日志级别,低于该级别的日志不会被记录。
- format:定义日志输出格式。
- datefmt:定义日期时间格式。
记录日志
使用不同级别的方法记录日志:
logging.debug('This is a debug message') logging.info('This is an info message') logging.warning('This is a warning message') logging.error('This is an error message') logging.critical('This is a critical message')
Logger、Handler 和 Formatter
创建 Logger
Logger 是日志记录的入口:
logger = logging.getLogger('my_logger') logger.setLevel(logging.DEBUG)
添加 Handler
Handler 决定日志输出的位置,例如文件或控制台。
FileHandler:输出到文件。
file_handler = logging.FileHandler('my_log.log') file_handler.setLevel(logging.DEBUG)
StreamHandler:输出到控制台。
console_handler = logging.StreamHandler() console_handler.setLevel(logging.INFO)
设置 Formatter
Formatter 决定日志的最终输出格式:
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') file_handler.setFormatter(formatter) console_handler.setFormatter(formatter)
将 Handler 添加到 Logger
logger.addHandler(file_handler) logger.addHandler(console_handler)
使用 Logger
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')
高级功能
日志配置文件
可以通过配置文件来管理日志设置,例如使用 logging.config 模块:
import logging.config import yaml with open('logging_config.yaml', 'r') as f: config = yaml.safe_load(f.read()) logging.config.dictConfig(config) 示例 logging_config.yaml: version: 1 formatters: simple: format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s' handlers: console: class: logging.StreamHandler level: DEBUG formatter: simple stream: ext://sys.stdout loggers: my_logger: level: DEBUG handlers: [console] propagate: no
自定义 Filter
可以创建自定义的 Filter 来实现更复杂的日志过滤:
class MyFilter(logging.Filter): def filter(self, record): return 'special' in record.msg my_filter = MyFilter() console_handler.addFilter(my_filter)
日志的层次结构
Logger 是分层次的,子记录器会继承父记录器的设置。例如:
parent_logger = logging.getLogger('parent') child_logger = logging.getLogger('parent.child') parent_logger.setLevel(logging.WARNING) child_logger.info('This will not be shown') child_logger.warning('This will be shown')
实践中的一些建议
使用建议
- 避免使用 root logger:尽量使用自定义的 logger,以便更好地管理和控制日志。
- 合理设置日志级别:在开发环境中可以设置较低的日志级别,如DEBUG,而在生产环境中应设置为较高的级别,如 WARNING 或 ERROR。
- 日志文件管理:对于输出到文件的日志,可以使用RotatingFileHandler 或 TimedRotatingFileHandler 来管理日志文件的大小和备份。
注意事项
- 日志性能:确保日志记录不会对程序性能造成显著影响,特别是在高频率的日志记录场景中。
- 日志轮换:使用 RotatingFileHandler 或 TimedRotatingFileHandler 处理大日志文件,避免日志文件过大。
- 日志安全:确保日志文件的安全性,避免敏感信息泄露。
- 通过合理使用 logging 模块,可以大大提高程序的可维护性和可调试性。