您现在的位置是:网站首页>文章详情文章详情

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设置分开关,以达到不同等级的日志消息按照不同的处理流程,如一般信息写入本地日志文件、错误信息给我们发送邮件等。

日志等级从小到大分别是:

等级数值
CRITICAL50
FATAL50
ERROR40
WARNING30
WARN30
INFO20
DEBUG10
NOTSET0

一般我们总日志开关设置为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)来导入配置,再实例化一个日志对象即可使用。

d7ab2438a63534d09e6720863dab41a312.png


很赞哦! ( 43)
    《Python实战进阶》
    None
    None
    夏至已深

站点信息

  • 建站时间:2019-5-24
  • 网站程序:like in love
  • 主题模板《今夕何夕》
  • 文章统计:104条
  • 文章评论:***条
  • 微信公众号:扫描二维码,关注我们
  • 个人微信公众号