zoukankan      html  css  js  c++  java
  • logging 日志模块学习

    logging

    日志模块,用于记录系统在运行过程中的一些关键信息,以便于对系统的运行状况进行跟踪,所以还是灰常重要滴,下面我就来从入门到放弃的系统学习一下日志既可以在屏幕上显示,又可以在文件中体现。

    简单的在屏幕上体现

    logging.debug('This is debug message')
    logging.info('This is info message')
    logging.warning('This is warning message')
    
    屏幕上打印:
    WARNING:root:This is warning message 

    默认情况下,logging将日志打印到屏幕,日志级别为WARNING;

    日志级别大小关系为:CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET,当然也可以自己定义日志级别

    输出到指定文件

    import logging
    
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                        datefmt='%a, %d %b %Y %H:%M:%S',
                        filename='test.log',
                        filemode='w')
    
    logging.debug('debug message')
    logging.info('info message')
    logging.warning('warning message')
    logging.error('error message')
    logging.critical('critical message')
    

    logging.basicConfig函数各参数:

    level :设置日志的级别.对低于该级别的日志消息将被忽略

    format :设置日志输出格式,format可以输出很多有用信息,如下所示:

        %(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: 打印日志信息

    datefmt :定义日期格式

    filename: 指定日志存储路径及文件名

    filemode :日志文件的打开模式。 默认值为’a',表示日志消息以追加的形式添加到日志文件中。如果设为’w', 那么每次程序启动的时候都会更新旧的日志文件

    stream: 指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略

    注意:

    basicConfig是为root logger创建的一个句柄(StreamHandler),如果root logger已经存在一个句柄时,basicConfig()函数并不会创建新的句柄,就是logging.basicConfig无论配置几个,都只能在一个文件中记录 ,想要在多个文件中记录的话,就需要自己写logging.FileHandler

    日志同时输出到文件和屏幕

    import logging
    
    # 1、创建一个logger
    logger = logging.getLogger('mylogger')
    logger.setLevel(logging.DEBUG)
    
    # 2、创建一个handler,用于写入日志文件
    fh = logging.FileHandler('test.log')
    fh.setLevel(logging.DEBUG)
    
    # 再创建一个handler,用于输出到控制台
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    
    # 3、定义handler的输出格式(formatter)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    # 4、给handler添加formatter
    fh.setFormatter(formatter)
    ch.setFormatter(formatter)
    
    # 5、给logger添加handler
    logger.addHandler(fh)
    logger.addHandler(ch)
    
    # 6、记录日志
    logger.debug("debug message")
    logger.info("info message")
    logger.warn("warn message")
    logger.error("error message")
    logger.critical("critical message")
    

    这里的logger.setlevel应该是设置的全局日志等级,后面的handler就可以不用设置了,当然也可以在handler重写日志等级,且日志等级必须大于这个全局日志等级才会生效

    典型的日志记录的步骤是这样的:

    1. 创建logger
    2. 创建handler
    3. 定义formatter
    4. 给handler添加formatter
    5. 给logger添加handler

    logging中几个比较中要的类

    除了基本的Handler类,比较有用的子类有:

    1) StreamHandler实例发送错误到流(类似文件的对象)

    2) FileHandler实例发送错误到磁盘文件

    3) BaseRotatingHandler是所有轮徇日志的基类,不能直接使用。但是可以使用 RotatingFileHandler和TimeRotatingFileHandler

    4) RotatingFileHandler实例发送信息到磁盘文件,并且限制最大的日志文件大小,并适时轮徇

    5) TimeRotatingFileHandler实例发送错误信息到磁盘,并在适当的事件间隔进行轮徇

    6) SocketHandler实例发送日志到TCP/IP socket。

    7) DatagramHandler实例发送错误信息通过UDP协议 

    8) SMTPHandler实例发送错误信息到特定的email地址 

    9) SysLogHandler实例发送日志到UNIX syslog服务,并支持远程syslog服务  

    10)NTEventLogHandler实例发送日志到WindowsNT/2000/XP事件日志

    11)MemoryHandler实例发送日志到内存中的缓冲区,并在达到特定条件时清空

    12)HTTPHandler实例发送错误信息到HTTP服务器,通过GET或POST方法

    现实应用:

    #/usr/bin/python
    #coding:utf-8
    
    import logging
    import sys,os
    import pdb
    
    class MyLog(object):
        '''
        Usage:
            mylog = MyLog()
            logger = mylog.getLog()
            logger.debug('test...')
            logger.info('test...')
            logger.warning('test...')
            logger.error('test...')
            logger.critical('test...')
        默认日志输出到日志文件
        缺省日志名字:调用者文件名后缀变为log 
            例如:my.py 调用mylog模块 则日志名字my.log
            如果需要设置自己的日志名字则:mylog.setLog(filename,loglevel)    
            
        如果同时向输出到屏幕则需要使用:mylog.openConsole(self,is_control = True,log_level = None)方法
        '''
        debug = logging.DEBUG
        info = logging.INFO
        warning = logging.WARNING
        error = logging.ERROR
        critical = logging.CRITICAL
        
        def __init__(self,log_level = logging.WARNING):
            self.log_level = log_level
            try:
                self.default_log_file = os.path.basename(sys.argv[0]).split('.')[0] + '.log'
            except:
                self.default_log_file = os.path.basename(sys.argv[0]) + '.log'
                
            logging.basicConfig(level=log_level,
                    format ='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt ='%a, %d %b %Y %H:%M:%S',
                    filename = self.default_log_file,
                    filemode ='w')
        @classmethod
        def _getFormatter(cls):
            fmt = logging.Formatter(fmt ='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt ='%a, %d %b %Y %H:%M:%S')
            return fmt
            
        def getLog(self):
            if not hasattr(self,'_logger'):
                self._logger = logging.getLogger()
            return self._logger
    
        def setLog(self,log_filename = None,log_level = None):
            if not hasattr(self,'_logger'):
                self._logger = logging.getLogger()
            else:
                #_handler存在,则移除旧_handler
                if hasattr(self,'_handler'):
                    self._logger.removeHandler(self._handler)
                    
            #实例化一个_hander
            if log_filename is None: 
                log_filename = self.default_log_file
            self._handler=logging.FileHandler(log_filename)
            
            #set log Formatter
            fmt = MyLog._getFormatter()
            self._handler.setFormatter(fmt)
            
            self._logger.addHandler(self._handler)
            
            if log_level is None:
                log_level = self.log_level
            self._logger.setLevel(log_level)
        
        def openConsole(self,is_control = True,log_level = None):
            '''
            默认输出屏幕级别与输出到日志的级别一致
            如果关闭屏幕输出:is_control 设置为False
            '''
            if not hasattr(self,'_logger'):
                self._logger = logging.getLogger()
                
            if is_control:
                fmt = MyLog._getFormatter()
                self._console = logging.StreamHandler()
                if log_level is not None:
                    try:
                        self._console.setLevel(log_level)
                    except:
                        raise Exception('log_level is Error!')
                self._console.setFormatter(fmt)
                self._logger.addHandler(self._console)
            else:
                if hasattr(self,'_console'):
                    self._logger.removeHandler(self._console)
    
    if __name__=='__main__':
        #pdb.set_trace()
        mylog = MyLog()
        mylog.setLog('11.log',logging.DEBUG)
        logger = mylog.getLog()
        mylog.openConsole()
        logger.info('Test...')
        mylog.openConsole(False)
        logger.info('close console...')
    View Code
  • 相关阅读:
    maven学习(二)
    maven学习(一)
    一步步点亮led之软硬件分析
    mkv210添加校验和
    led部分Makefile
    makefile
    交叉编译工具链
    基础知识
    C语言复杂表达式与指针应用
    指针
  • 原文地址:https://www.cnblogs.com/luxiaojun/p/6180029.html
Copyright © 2011-2022 走看看