今天在崔大大的博客中看到了python logging 模块的学习,受益匪浅,记录下来链接:https://cuiqingcai.com/6080.html ,方便日后查看。
以下是部分学习记录:
## 1、基础使用
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(pathname)s : %(lineno)s : %(message)s',
level=logging.INFO, filename='log.txt')
logging.error('222222222222') # exc_info=True 可以输出完整的保存信息,适用于捕获错误
format:指定日志信息的输出格式,即上文示例所示的参数,详细参数可以参考:docs.python.org/3/library/l…,部分参数如下所示:
- %(levelno)s:打印日志级别的数值。
- %(levelname)s:打印日志级别的名称。
- %(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0]。
- %(filename)s:打印当前执行程序名。
- %(funcName)s:打印日志的当前函数。
- %(lineno)d:打印日志的当前行号。
- %(asctime)s:打印日志的时间。
- %(thread)d:打印线程ID。
- %(threadName)s:打印线程名称。
- %(process)d:打印进程ID。
- %(processName)s:打印线程名称。
- %(module)s:打印模块名称。
- %(message)s:打印日志信息。
## 2、Handler
# handler使用
import logging
from logging.handlers import HTTPHandler
import sys
logger = logging.getLogger(__name__)
logger.setLevel(level=logging.DEBUG)
# StreamHandler 控制台输出
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setLevel(level=logging.DEBUG)
logger.addHandler(stream_handler)
# FileHandler 文件输出
file_handler = logging.FileHandler('output.log')
file_handler.setLevel(level=logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
# HTTPHandler 通过”GET”或者”POST”远程输出到HTTP服务器。
http_handler = HTTPHandler(host='localhost:8001', url='log', method='POST')
logger.addHandler(http_handler)
# Log
logger.info('This is a log info')
logger.debug('Debugging')
logger.warning('Warning exists')
logger.info('Finish')
# 这样一来,我们就通过设置多个 Handler 来控制了日志的多目标输出。
# 还可以通过Formatter给每个 Handler 单独配置输出的格式,非常灵活。
# logging 模块提供的 Handler 有
"""
StreamHandler:logging.StreamHandler;日志输出到流,可以是 sys.stderr,sys.stdout 或者文件。
FileHandler:logging.FileHandler;日志输出到文件。
BaseRotatingHandler:logging.handlers.BaseRotatingHandler;基本的日志回滚方式。
RotatingHandler:logging.handlers.RotatingHandler;日志回滚方式,支持日志文件最大数量和日志文件回滚。
TimeRotatingHandler:logging.handlers.TimeRotatingHandler;日志回滚方式,在一定时间区域内回滚日志文件。
SocketHandler:logging.handlers.SocketHandler;远程输出日志到TCP/IP sockets。
DatagramHandler:logging.handlers.DatagramHandler;远程输出日志到UDP sockets。
SMTPHandler:logging.handlers.SMTPHandler;远程输出日志到邮件地址。
SysLogHandler:logging.handlers.SysLogHandler;日志输出到syslog。
NTEventLogHandler:logging.handlers.NTEventLogHandler;远程输出日志到Windows NT/2000/XP的事件日志。
MemoryHandler:logging.handlers.MemoryHandler;日志输出到内存中的指定buffer。
HTTPHandler:logging.handlers.HTTPHandler;通过”GET”或者”POST”远程输出到HTTP服务器。
"""
## 3、配置共享
在写项目的时候,我们肯定会将许多配置放置在许多模块下面,这时如果我们每个文件都来配置 logging 配置那就太繁琐了,logging 模块提供了父子模块共享配置的机制,会根据 Logger 的名称来自动加载父模块的配置。
例如我们这里首先定义一个 main.py 文件:
import logging
import core
logger = logging.getLogger('main')
logger.setLevel(level=logging.DEBUG)
# Handler
handler = logging.FileHandler('result.log')
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.info('Main Info')
logger.debug('Main Debug')
logger.error('Main Error')
core.run()
这里我们配置了日志的输出格式和文件路径,同时定义了 Logger 的名称为 main,然后引入了另外一个模块 core,最后调用了 core 的 run() 方法。
接下来我们定义 core.py,内容如下:
import logging
logger = logging.getLogger('main.core')
def run():
logger.info('Core Info')
logger.debug('Core Debug')
logger.error('Core Error')
这里我们定义了 Logger 的名称为 main.core,注意这里开头是 main,即刚才我们在 main.py 里面的 Logger 的名称,这样 core.py 里面的 Logger 就会复用 main.py 里面的 Logger 配置,而不用再去配置一次了。
运行之后会生成一个 result.log 文件,内容如下:
2018-06-03 16:55:56,259 - main - INFO - Main Info
2018-06-03 16:55:56,259 - main - ERROR - Main Error
2018-06-03 16:55:56,259 - main.core - INFO - Core Info
2018-06-03 16:55:56,259 - main.core - ERROR - Core Error
可以看到父子模块都使用了同样的输出配置。
如此一来,我们只要在入口文件里面定义好 logging 模块的输出配置,子模块只需要在定义 Logger 对象时名称使用父模块的名称开头即可共享配置,非常方便。