您现在的位置是:网站首页>文章详情文章详情
Python日志模块相关问题
inlike2019-09-23【 原创文章 】 浏览(1970) 评论(0) 喜欢(43)
简介总结一下使用Python日志模块遇到的一些问题和常用的日志模块源码,涉及基本使用、日志重复输出问题、日志穿透问题、日志存储、日志分割、日志模块的其他常用功能等。
总结一下使用Python日志模块遇到的一些问题和常用的日志模块源码,涉及基本使用、日志重复输出问题、日志穿透问题、日志存储、日志分割、日志模块的其他常用功能等。
日志使用流程
使用Python的logging模块的时候,首先是实例化logging模块,实例化使用logging.getLogger(name)传入日志名从获得已创建的日志对象或者新建一个日志对象,如果为空则会使用根日志;实例化后就是设置日志等级开关,制定日志的处理流程Handler及日志内容的格式化;注意日志可以设置多个Handler(处理流程),重复设置会导致日志重复输出的问题。
基本的使用示例
class LoggerLoggert:
"""自动创建日志文件"""
def __init__(self, filename='./static/logger.log'):
logging.getLogger("pika").propagate = False # 不捕获输出该日志的内容
logging.getLogger("selenium").propagate = False
logging.getLogger("sftp").propagate = False
logging.getLogger('transport').propagate = False
logging.getLogger('thran').propagate = False
logging.getLogger('paramiko').propagate = False
logging.getLogger('threading').propagate = False
self.logger = logging.getLogger()
self.logger.setLevel(logging.DEBUG) # Log等级总开关
# 第二步,创建一个handler,用于写入日志文件
logfile = filename
fh = logging.handlers.TimedRotatingFileHandler(filename=logfile, when="D", interval=1,
backupCount=5, encoding='utf-8') # 按照时间分割日志
# fh = logging.handlers.RotatingFileHandler(filename=logfile, maxBytes=100, backupCount=5) # 按日志文件大小分割日志
# fh = logging.FileHandler(logfile, mode='a') # 正常使用日志
fh.setLevel(logging.DEBUG) # 输出到file的log等级的开关
# 第三步,再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG) # 输出到console的log等级的开关
# 第四步,定义handler的输出格式
formatter = logging.Formatter(
"%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# 第五步,将logger添加到handler里面
self.logger.addHandler(fh)
self.logger.addHandler(ch)
def debug(self, msg):
self.logger.debug(msg)
def info(self, msg):
self.logger.info(msg)
def warning(self, msg):
self.logger.warning(msg)
def error(self, msg):
self.logger.error(msg)
def critical(self, msg):
self.logger.critical(msg)
def exception(self, msg):
self.logger.exception(msg)
不捕获输入其他模块内的日志
import logging
logging.getLogger("pika").propagate = False # 不捕获输出该日志的内容
日志追加或者重写
fh = logging.FileHandler(logfile, mode='a')
mode参数决定是重写还是追加在原日志文件中
按时间分割日志
fh = logging.handlers.TimedRotatingFileHandler(filename=logfile, when="D", interval=1,
backupCount=5, encoding='utf-8') # 按照时间分割日志
创建Handler的时候选择TimedRotatingFileHandler,when参数是时间单位、interval是日志文件分割周期,backupCount是滚动保留的日志文件数为0则保留全部,上面配置的意思是:每天一个日志文件,保留最近5天的日志文件。
when是时间单位,可选择的如下:
“S”: Seconds
“M”: Minutes
“H”: Hours
“D”: Days
“W”: Week day (0=Monday)
“midnight”: Roll over at midnight
按日志文件大小分割日志
fh = logging.handlers.RotatingFileHandler(filename=logfile, maxBytes=100, backupCount=5) # 按日志文件大小分割日志
创建Handler的时候选择RotatingFileHandler,maxBytes参数是日志文件的大小
日志设置等级
可以给实例化的设置对象设置日志等级总开关,也可以不同的Handler设置分开关,以达到不同等级的日志消息按照不同的处理流程,如一般信息写入本地日志文件、错误信息给我们发送邮件等。
日志等级从小到大分别是:
等级 | 数值 |
---|---|
CRITICAL | 50 |
FATAL | 50 |
ERROR | 40 |
WARNING | 30 |
WARN | 30 |
INFO | 20 |
DEBUG | 10 |
NOTSET | 0 |
一般我们总日志开关设置为DEBUG,然后Headle开关可以设置DEBUG及其以上的等级,从而实现不同情况不同的处理Headle。
日志消息格式化
在保存日志消息的时候不仅需要msg,更需要一些其他信息来帮助我们定位异常或者错误,这个时候日志的格式化输出就非常有必要了,格式化是在穿件了Headle的基础上设置的:
fh = logging.handlers.RotatingFileHandler(filename=logfile, maxBytes=100, backupCount=5) # 按日志文件大小分割日志
formatter = logging.Formatter(
"%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
fh.setFormatter(formatter)
格式化支持的字段如下:
字段 | 含义 |
---|---|
%(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 |
%(message)s | 打印日志信息 |
日志其他有用的Headele处理流
发送邮件 注意:官方日志不支持SMTP_SSL因此qq邮箱不能用,163可以使用
import logging
from logging.handlers import SMTPHandler
import sys
def main():
# 1. 创建 logger 实例
logger = logging.getLogger('test-smtphandler')
# 2. 设置 logger 实例的日志级别,默认是 logging.WARNING
logger.setLevel(logging.INFO)
# 3. 创建 Handler
# 注意 163 邮箱要求 fromaddr 和你发送邮件的邮箱(即你的邮箱账号)要一致
mail_handler = SMTPHandler(
mailhost=('smtp.163.com', 25),
fromaddr='xxx@163.com',
toaddrs='接收报警邮件的地址',
subject='[madmalls.com] 服务器出错了',
credentials=('xxx@163.com', '客户端授权密码'))
# 4. 单独设置 mail_handler 的日志级别为 ERROR
mail_handler.setLevel(logging.ERROR)
# 5. 将 Handler 添加到 logger 中
logger.addHandler(mail_handler)
# 6. 应用的业务代码(故意出错)
try:
x = 1 / 0
except Exception:
logger.error('[计算出错了] x = 1 / 0', exc_info=sys.exc_info())
修改版可用参考:https://blog.csdn.net/weixin_33670713/article/details/86018789
通过http发送至接口
import logging
from logging.handlers import HTTPHandler
logger = logging.getLogger(__name__)
logger.setLevel(level=logging.DEBUG)
http_handler = HTTPHandler(host='localhost:8001', url='log', method='POST')
logger.addHandler(http_handler)
其他相关Headle
StreamHandler:logging.StreamHandler;日志输出到流,可以是 sys.stderr,sys.stdout 或者文件。
SocketHandler:logging.handlers.SocketHandler;远程输出日志到TCP/IP sockets。
DatagramHandler:logging.handlers.DatagramHandler;远程输出日志到UDP sockets。
SysLogHandler:logging.handlers.SysLogHandler;日志输出到syslog。
NTEventLogHandler:logging.handlers.NTEventLogHandler;远程输出日志到Windows NT/2000/XP的事件日志。
MemoryHandler:logging.handlers.MemoryHandler;日志输出到内存中的指定buffer。
显示更多错误及异常信息
在error级别日志信息写入时调用exc_info=True,来记录更多错误信息。
logger.error(e, exc_info=True)
通过json配置日志文件
{ "version": 1, "disable_existing_loggers": false, // 日志格式 "formatters": { "simple": { "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s" } }, "handlers": { // 定义控制台日志的级别和样式 "console": { "class": "logging.StreamHandler", "level": "DEBUG", "formatter": "simple", "stream": "ext://sys.stdout" }, // 定义INFO(以上)级别的日志处理器 "info_file_handler": { "class": "logging.handlers.RotatingFileHandler", "level": "INFO", "formatter": "simple", "filename": "./logs/info.log", "maxBytes": 10485760, "backupCount": 20, "encoding": "utf8" }, // 定义ERROR以上)级别的日志处理器 "error_file_handler": { "class": "logging.handlers.RotatingFileHandler", "level": "ERROR", "formatter": "simple", "filename": "./logs/errors.log", "maxBytes": 10485760, "backupCount": 20, "encoding": "utf8" } }, // 定义不同name的logger的日志配置, "loggers": { "mymodule": { "level": "ERROR", "handlers": [ "info_file_handler" ], "propagate": "no" } }, // 定义全局日志配置 "root": { "level": "INFO", "handlers": [ "console", "info_file_handler", "error_file_handler" ] } }
配置json格式化后,就需要通过logging.config.dictConfig(LOGGING_SETTING)来导入配置,再实例化一个日志对象即可使用。
相关文章
本栏推荐
标签云
猜你喜欢
站点信息
- 建站时间:2019-5-24
- 网站程序:like in love
- 主题模板:《今夕何夕》
- 文章统计:104条
- 文章评论:***条
- 微信公众号:扫描二维码,关注我们