logging_logging模块 - CSDN
精华内容
参与话题
  • Python中的logging模块就这么用

    万次阅读 多人点赞 2015-05-21 18:32:34
    logfile = 'log.txt' ...logger = logging.getLogger() hdlr = logging.FileHandler(logfile) formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') hdlr.setFormatter(formatter)

    1、日志级别

    日志一共分成5个等级,从低到高分别是:DEBUG INFO WARNING ERROR CRITICAL。

    DEBUG:详细的信息,通常只出现在诊断问题上
    INFO:确认一切按预期运行
    WARNING:一个迹象表明,一些意想不到的事情发生了,或表明一些问题在不久的将来(例如。磁盘空间低”)。这个软件还能按预期工作。
    ERROR:更严重的问题,软件没能执行一些功能
    CRITICAL:一个严重的错误,这表明程序本身可能无法继续运行

    这5个等级,也分别对应5种打日志的方法: debug 、info 、warning 、error 、critical。默认的是WARNING,当在WARNING或之上时才被跟踪。


    2、日志输出

    有两种方式记录跟踪,一种输出控制台,另一种是记录到文件中,如日志文件。


    2.1、将日志输出到控制台

    比如,编写一个叫做log.py的文件,如下:

    # coding=utf-8
    __author__ = 'liu.chunming'
    import logging
    
    logging.basicConfig(level=logging.WARNING,
                        format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
    # use logging
    logging.info('this is a loggging info message')
    logging.debug('this is a loggging debug message')
    logging.warning('this is loggging a warning message')
    logging.error('this is an loggging error message')
    logging.critical('this is a loggging critical message')
    执行上面的代码将在Console中输出下面信息:

    C:\Python27\python.exe C:/Users/liu.chunming/PycharmProjects/Myproject/log.py
    2015-05-21 17:25:22,572 - log.py[line:10] - WARNING: this is loggging a warning message
    2015-05-21 17:25:22,572 - log.py[line:11] - ERROR: this is an loggging error message
    2015-05-21 17:25:22,572 - log.py[line:12] - CRITICAL: this is a loggging critical message

    【解析】

    通过logging.basicConfig函数对日志的输出格式及方式做相关配置,上面代码设置日志的输出等级是WARNING级别,意思是WARNING级别以上的日志才会输出。另外还制定了日志输出的格式。


    2.2、将日志输出到文件

    我们还可以将日志输出到文件,只需要在logging.basicConfig函数中设置好输出文件的文件名和写文件的模式。

    # coding=utf-8
    __author__ = 'liu.chunming'
    import logging
    
    logging.basicConfig(level=logging.WARNING,
                        filename='./log/log.txt',
                        filemode='w',
                        format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
    # use logging
    logging.info('this is a loggging info message')
    logging.debug('this is a loggging debug message')
    logging.warning('this is loggging a warning message')
    logging.error('this is an loggging error message')
    logging.critical('this is a loggging critical message')
    运行之后,打开该文件./log/log.txt,效果如下:

    2015-05-21 17:30:20,282 - log.py[line:12] - WARNING: this is loggging a warning message
    2015-05-21 17:30:20,282 - log.py[line:13] - ERROR: this is an loggging error message
    2015-05-21 17:30:20,282 - log.py[line:14] - CRITICAL: this is a loggging critical message


    2.3、既要把日志输出到控制台, 还要写入日志文件

    这就需要一个叫作Logger 的对象来帮忙,下面将对他进行详细介绍,现在这里先学习怎么实现把日志既要输出到控制台又要输出到文件的功能。

    # coding=utf-8
    __author__ = 'liu.chunming'
    import logging
    
    # 第一步,创建一个logger
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)    # Log等级总开关
    
    # 第二步,创建一个handler,用于写入日志文件
    logfile = './log/logger.txt'
    fh = logging.FileHandler(logfile, mode='w')
    fh.setLevel(logging.DEBUG)   # 输出到file的log等级的开关
    
    # 第三步,再创建一个handler,用于输出到控制台
    ch = logging.StreamHandler()
    ch.setLevel(logging.WARNING)   # 输出到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里面
    logger.addHandler(fh)
    logger.addHandler(ch)
    
    # 日志
    logger.debug('this is a logger debug message')
    logger.info('this is a logger info message')
    logger.warning('this is a logger warning message')
    logger.error('this is a logger error message')
    logger.critical('this is a logger critical message')
    
    执行这段代码之后,在console中,可以看到:

    C:\Python27\python.exe C:/Users/liu.chunming/PycharmProjects/Myproject/log.py
    2015-05-21 17:47:50,292 - log.py[line:30] - WARNING: this is a logger warning message
    2015-05-21 17:47:50,292 - log.py[line:31] - ERROR: this is a logger error message
    2015-05-21 17:47:50,293 - log.py[line:32] - CRITICAL: this is a logger critical message
    在logger.txt中,可以看到:

    2015-05-21 17:47:50,292 - log.py[line:29] - INFO: this is a logger info message
    2015-05-21 17:47:50,292 - log.py[line:30] - WARNING: this is a logger warning message
    2015-05-21 17:47:50,292 - log.py[line:31] - ERROR: this is a logger error message
    2015-05-21 17:47:50,293 - log.py[line:32] - CRITICAL: this is a logger critical message

    
    

    【解析】

    可以发现,实现这个功能一共分5步:

    第一步,创建一个logger;第二步,创建一个handler,用于写入日志文件;第三步,再创建一个handler,用于输出到控制台;第四步,定义handler的输出格式;第五步,将logger添加到handler里面。这段代码里面提到了好多概念,包括:Logger,Handler,Formatter。后面讲对这些概念进行讲解。

    3、多个模块中日志输出顺序

    通常我们的工作中会有多个模块都需要输出日志。那么,具有调用关系的模块之间,它门的日志输出顺序是怎么样的?我们来演示下:假设有两个文件,分别是util.py:
    # util.py
    __author__ = 'liu.chunming'
    import logging
    
    def fun():
        logging.info('this is a log in util module')
    和main.py
    # main.py
    # coding=utf-8
    __author__ = 'liu.chunming'
    import logging
    import util
    
    logging.basicConfig(level=logging.INFO,
                        filename='./log/log.txt',
                        filemode='w',
                        format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
    def main():
        logging.info('main module start')
        util.fun()
        logging.info('main module stop')
    
    if __name__ == '__main__':
        main()
    运行后打开log.txt,结果如下:
    2015-05-21 18:10:34,684 - main.py[line:11] - INFO: main module start
    2015-05-21 18:10:34,684 - util.py[line:5] - INFO: this is a log in util module
    2015-05-21 18:10:34,684 - main.py[line:13] - INFO: main module stop
    【解析】
    可以看出,日志的输出顺序就是模块的执行顺序。

    4、日志格式说明

    logging.basicConfig函数中,可以指定日志的输出格式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: 打印日志信息

    我在工作中给的常用格式在前面已经看到了。就是:

    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s'

    这个格式可以输出日志的打印时间,是哪个模块输出的,输出的日志级别是什么,以及输入的日志内容。

    5、高级进阶

    接下来学习一些日志组件以及一些高级部分。日志组件包括:loggers、handlers,filters,formatters.

    Logger 对象扮演了三重角色.首先,它暴露给应用几个方法以便应用可以在运行时写log.其次,Logger对象按照log信息的严重程度或者根据filter对 象来决定如何处理log信息(默认的过滤功能).最后,logger还负责把log信息传送给相关的loghandlers.

    Handler对象负责分配合适的log信息(基于log信息的严重 程度)到handler指定的目的地.Logger对象可以用addHandler()方法添加零个或多个handler对象到它自身.一个常见的场景 是,一个应用可能希望把所有的log信息都发送到一个log文件中去,所有的error级别以上的log信息都发送到stdout,所有critical 的log信息通过email发送.这个场景里要求三个不同handler处理,每个handler负责把特定的log信息发送到特定的地方.

    filter:细致化,选择哪些日志输出

    format:设置显示格式

    1、logging.basicConfig([**kwargs]):

    Does basic configuration for the logging system by creating a StreamHandler with a defaultFormatter and adding it to the root logger. The functionsdebug(),info(),warning(),error() andcritical() will callbasicConfig() automatically if no handlers are defined for the root logger.

    This function does nothing if the root logger already has handlers configured for it.

    为日志模块配置基本信息。kwargs 支持如下几个关键字参数:
    filename :日志文件的保存路径。如果配置了些参数,将自动创建一个FileHandler作为Handler;
    filemode
    :日志文件的打开模式。 默认值为'a',表示日志消息以追加的形式添加到日志文件中。如果设为'w', 那么每次程序启动的时候都会创建一个新的日志文件;
    format :设置日志输出格式;
    datefmt :定义日期格式;
    level :设置日志的级别.对低于该级别的日志消息将被忽略;
    stream :设置特定的流用于初始化StreamHandler;

    演示如下:

    复制代码
    import logging
    import os
    FILE=os.getcwd()
    
    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 = os.path.join(FILE,'log.txt'),
                        filemode='w')
    logging.info('msg')
    logging.debug('msg2')
    复制代码

    2、logging.getLogger([name])

    创建Logger对象。日志记录的工作主要由Logger对象来完成。在调用getLogger时要提供Logger的名称(注:多次使用相同名称 来调用getLogger,返回的是同一个对象的引用。),Logger实例之间有层次关系,这些关系通过Logger名称来体现,如:

    p = logging.getLogger("root")

    c1 = logging.getLogger("root.c1")

    c2 = logging.getLogger("root.c2")

    例子中,p是父logger, c1,c2分别是p的子logger。c1, c2将继承p的设置。如果省略了name参数, getLogger将返回日志对象层次关系中的根Logger。

    复制代码
    import logging
    '''命名'''
    log2=logging.getLogger('BeginMan')  #生成一个日志对象
    print log2  #<logging.Logger object at 0x00000000026D1710>
    
    '''无名'''
    log3 = logging.getLogger()
    print log3  #<logging.RootLogger object at 0x0000000002721630> 如果没有指定name,则返回RootLogger
    
    '''最好的方式'''
    log = logging.getLogger(__name__)#__name__ is the module’s name in the Python package namespace.
    print log   #<logging.Logger object at 0x0000000001CD5518>  Logger对象
    print __name__  #__main__
    复制代码

    三、Logger对象

    通过logging.getLogger(nam)来获取Logger对象,

    Class logging.Logger

    有如下属性和方法:

    1、Logger.propagate

    print log.propagate         #1

    具体参考:http://docs.python.org/2.7/library/logging.html

    2、Logger.setLevel(lvl)

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

    复制代码
    import logging
    import os
    logging.basicConfig(format="%(levelname)s,%(message)s",filename=os.path.join(os.getcwd(),'log.txt'),level=logging.DEBUG)
    log = logging.getLogger('root.set')   #Logger对象
    print log.propagate         #1
    log.setLevel(logging.WARN)  #日志记录级别为WARNNING  
    log.info('msg')             #不会被记录
    log.debug('msg')            #不会被记录
    log.warning('msg')
    log.error('msg')
    复制代码

    3、Logger.debug(msg [ ,*args [, **kwargs]])

    记录DEBUG级别的日志信息。参数msg是信息的格式,args与kwargs分别是格式参数。

    复制代码
    import logging
    logging.basicConfig(filename = os.path.join(os.getcwd(), 'log.txt'), level = logging.DEBUG)
    log = logging.getLogger('root')
    log.debug('%s, %s, %s', *('error', 'debug', 'info'))
    log.debug('%(module)s, %(info)s', {'module': 'log', 'info': 'error'})
    复制代码

    4、同上

    Logger.info(msg[ , *args[ , **kwargs] ] )

    Logger.warnning(msg[ , *args[ , **kwargs] ] )

    Logger.error(msg[ , *args[ , **kwargs] ] )

    Logger.critical(msg[ , *args[ , **kwargs] ] )

    5、Logger.log(lvl, msg[ , *args[ , **kwargs]] )

    记录日志,参数lvl用户设置日志信息的级别。参数msg, *args, **kwargs的含义与Logger.debug一样。

    log.log(logging.ERROR,'%(module)s %(info)s',{'module':'log日志','info':'error'}) #ERROR,log日志 error
    log.log(logging.ERROR,'再来一遍:%s,%s',*('log日志','error'))  #ERROR,再来一遍:log日志,error

    6、Logger.exception(msg[, *args])

    以ERROR级别记录日志消息,异常跟踪信息将被自动添加到日志消息里。Logger.exception通过用在异常处理块中,如:

    复制代码
    import logging
    import os
    logging.basicConfig(format="%(levelname)s,%(message)s",filename=os.path.join(os.getcwd(),'log.txt'),level=logging.DEBUG)
    log = logging.getLogger('root')   #Logger对象
    try:
        raise Exception,u'错误异常'
    except:
        log.exception('exception')  #异常信息被自动添加到日志消息中  
    打开文件,显示如下:
    
    '''ERROR,exception
    Traceback (most recent call last):
      File "E:\project\py\src\log3.py", line 12, in <module>
        raise Exception,u'错误异常'
    Exception: 错误异常
    '''
    复制代码

    7、Logger.addFilter(filt)

    指定过滤器

    8、Logger.removeFilter(filt)

    移除指定的过滤器

    9、Logger.filter(record)

    ....其他的后面介绍

    四、 Handler对象、Formatter对象、Filter对象、Filter对象

    这里简要介绍

    复制代码
    #coding=utf8
    '''
    Created on 2013年9月23日
    Function : Handler对象、Formatter对象、Filter对象、Filter对象
    @author : BeginMan
    '''
    import logging
    import os
    '''Logger'''
    l = logging.Logger('root')          #创建Logger对象
    log = logging.getLogger('root')     #通过logging.getLogger创建Logger对象
    print l                             #<logging.Logger object at 0x0000000001DF5B70>
    print log                           #<logging.Logger object at 0x00000000022A16D8>
    
    '''Handler'''
    handler = logging.Handler()         #创建Handler对象
    handler.__init__(logging.DEBUG)     #通过设置level来初始化Handler实例
    handler.createLock()                #初始化一个线程锁可以用来序列化访问底层I / O功能,这可能不是线程安全的。
    handler.acquire()                   #获取线程锁通过handler.createLock()
    handler.release()                   #释放线程锁通过获取handler.acquire()
    handler.setLevel(logging.DEBUG)     #设置临界值,如果Logging信息级别小于它则被忽视,当一个handler对象被创建,级别没有被设置,导致所有的信息会被处理。
    handler.setFormatter("%(levelname)s,%(message)s")              #设置格式
    # handler.addFilter(filter)         #添加指定的过滤器
    # handler.removeFilter(filter)      #移除指定的过滤器
    # handler.filter(record)            #通过设置过滤器适用于记录并返回真值如果要处理的记录
    handler.flush()                     #确保所有的日志输出已经被刷新
    handler.close()                     #收拾任何所使用资源处理程序,
    # handler.handle(record)            #有条件地发出指定的日志记录,这取决于过滤器可能被添加到处理程序。
    # handler.handlerError(record)      #处理错误
    # handler.format(record)            #格式输出
    # handler.emit(record)
    
    #Formatter:http://docs.python.org/2.7/library/logging.html#logging.Formatter
    
    '''Formatter:
    the base Formatter allows a formatter string to be specified,is none ,used default value '%(message)s'
    class logging.Formatter(fmt=None,datefmt=None)
    If no fmt is specified, '%(message)s' is used. If no datefmt is specified, the ISO8601 date format is used.
    '''
    fm = logging.Formatter('%(levelname)s:%(message)s','%m/%d/%Y %I:%M:%S %p')
    print fm        #<logging.Formatter object at 0x0000000002311828>
    #有如下方法:format()、formatTime()、formatException()
    
    #http://docs.python.org/2.7/library/logging.html#formatter-objects
    
    '''Filter'''
    '''
    class logging.Filter(name=''):
        返回Filter实例,If name is specified, it names a logger which, together with its children, 
      will have its events allowed through the filter. If name is the empty string, allows every event.
    用于Loggers、Handlers等过滤的设置
    如果一个过滤器初始化为'A.B',则允许'A.B/A.B.C/A.B.C.D/A.B.D'等,但不允许'A.BB/B.A'等通过
    如果初始化为空字符串,则没有过滤。
    它有filter()方法
    '''
    
    '''LogRecord '''
    '''class logging.LogRecord(name, level, pathname, lineno, msg, args, exc_info, func=None)
    LogRecord 实例可以被Logger自动创建.也可以通过makeLogRecord()来创建'''
    #http://docs.python.org/2.7/library/logging.html#logrecord-objects

     

    展开全文
  • Python logging模块详解

    万次阅读 多人点赞 2014-05-06 16:17:57
    import logging logging.debug('debug message') logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message')输出: WARNI
    简单将日志打印到屏幕:
    import logging
    logging.debug('debug message')
    logging.info('info message')
    logging.warning('warning message')
    logging.error('error message')
    logging.critical('critical message')

    输出:

    WARNING:root:warning message
    ERROR:root:error message
    CRITICAL:root:critical message

    可见,默认情况下python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET),默认的日志格式为日志级别:Logger名称:用户输出消息。


    灵活配置日志级别,日志格式,输出位置
    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='/tmp/test.log',
                        filemode='w')
    
    logging.debug('debug message')
    logging.info('info message')
    logging.warning('warning message')
    logging.error('error message')
    logging.critical('critical message')
    查看输出:
    cat /tmp/test.log 
    Mon, 05 May 2014 16:29:53 test_logging.py[line:9] DEBUG debug message
    Mon, 05 May 2014 16:29:53 test_logging.py[line:10] INFO info message
    Mon, 05 May 2014 16:29:53 test_logging.py[line:11] WARNING warning message
    Mon, 05 May 2014 16:29:53 test_logging.py[line:12] ERROR error message
    Mon, 05 May 2014 16:29:53 test_logging.py[line:13] CRITICAL critical message

    可见在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有
    filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
    filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
    format:指定handler使用的日志显示格式。
    datefmt:指定日期时间格式。
    level:设置rootlogger(后边会讲解具体概念)的日志级别
    stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。

    format参数中可能用到的格式化串:
    %(name)s Logger的名字
    %(levelno)s 数字形式的日志级别
    %(levelname)s 文本形式的日志级别
    %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
    %(filename)s 调用日志输出函数的模块的文件名
    %(module)s 调用日志输出函数的模块名
    %(funcName)s 调用日志输出函数的函数名
    %(lineno)d 调用日志输出函数的语句所在的代码行
    %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
    %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
    %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
    %(thread)d 线程ID。可能没有
    %(threadName)s 线程名。可能没有
    %(process)d 进程ID。可能没有
    %(message)s用户输出的消息


    若要对logging进行更多灵活的控制有必要了解一下Logger,Handler,Formatter,Filter的概念
    上述几个例子中我们了解到了logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical()(分别用以记录不同级别的日志信息),logging.basicConfig()(用默认日志格式(Formatter)为日志系统建立一个默认的流处理器(StreamHandler),设置基础配置(如日志级别等)并加到root logger(根Logger)中)这几个logging模块级别的函数,另外还有一个模块级别的函数是logging.getLogger([name])(返回一个logger对象,如果没有指定名字将返回root logger)

    先看一个具体的例子
    #coding:utf-8
    import logging
    
    # 创建一个logger  
    logger = logging.getLogger()
    
    logger1 = logging.getLogger('mylogger')
    logger1.setLevel(logging.DEBUG)
    
    logger2 = logging.getLogger('mylogger')
    logger2.setLevel(logging.INFO)
    
    logger3 = logging.getLogger('mylogger.child1')
    logger3.setLevel(logging.WARNING)
    
    logger4 = logging.getLogger('mylogger.child1.child2')
    logger4.setLevel(logging.DEBUG)
    
    logger5 = logging.getLogger('mylogger.child1.child2.child3')
    logger5.setLevel(logging.DEBUG)
    
    # 创建一个handler,用于写入日志文件  
    fh = logging.FileHandler('/tmp/test.log')
    
    # 再创建一个handler,用于输出到控制台  
    ch = logging.StreamHandler()
    
    # 定义handler的输出格式formatter  
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    ch.setFormatter(formatter)
    
    #定义一个filter
    #filter = logging.Filter('mylogger.child1.child2')
    #fh.addFilter(filter)  
    
    # 给logger添加handler  
    #logger.addFilter(filter)
    logger.addHandler(fh)
    logger.addHandler(ch)
    
    #logger1.addFilter(filter)
    logger1.addHandler(fh)
    logger1.addHandler(ch)
    
    logger2.addHandler(fh)
    logger2.addHandler(ch)
    
    #logger3.addFilter(filter)
    logger3.addHandler(fh)
    logger3.addHandler(ch)
    
    #logger4.addFilter(filter)
    logger4.addHandler(fh)
    logger4.addHandler(ch)
    
    logger5.addHandler(fh)
    logger5.addHandler(ch)
    
    # 记录一条日志  
    logger.debug('logger debug message')
    logger.info('logger info message')
    logger.warning('logger warning message')
    logger.error('logger error message')
    logger.critical('logger critical message')
    
    logger1.debug('logger1 debug message')
    logger1.info('logger1 info message')
    logger1.warning('logger1 warning message')
    logger1.error('logger1 error message')
    logger1.critical('logger1 critical message')
    
    logger2.debug('logger2 debug message')
    logger2.info('logger2 info message')
    logger2.warning('logger2 warning message')
    logger2.error('logger2 error message')
    logger2.critical('logger2 critical message')
    
    logger3.debug('logger3 debug message')
    logger3.info('logger3 info message')
    logger3.warning('logger3 warning message')
    logger3.error('logger3 error message')
    logger3.critical('logger3 critical message')
    
    logger4.debug('logger4 debug message')
    logger4.info('logger4 info message')
    logger4.warning('logger4 warning message')
    logger4.error('logger4 error message')
    logger4.critical('logger4 critical message')
    
    logger5.debug('logger5 debug message')
    logger5.info('logger5 info message')
    logger5.warning('logger5 warning message')
    logger5.error('logger5 error message')
    logger5.critical('logger5 critical message')
    输出:
    2014-05-06 12:54:43,222 - root - WARNING - logger warning message
    2014-05-06 12:54:43,223 - root - ERROR - logger error message
    2014-05-06 12:54:43,224 - root - CRITICAL - logger critical message
    2014-05-06 12:54:43,224 - mylogger - INFO - logger1 info message
    2014-05-06 12:54:43,224 - mylogger - INFO - logger1 info message
    2014-05-06 12:54:43,225 - mylogger - WARNING - logger1 warning message
    2014-05-06 12:54:43,225 - mylogger - WARNING - logger1 warning message
    2014-05-06 12:54:43,226 - mylogger - ERROR - logger1 error message
    2014-05-06 12:54:43,226 - mylogger - ERROR - logger1 error message
    2014-05-06 12:54:43,227 - mylogger - CRITICAL - logger1 critical message
    2014-05-06 12:54:43,227 - mylogger - CRITICAL - logger1 critical message
    2014-05-06 12:54:43,228 - mylogger - INFO - logger2 info message
    2014-05-06 12:54:43,228 - mylogger - INFO - logger2 info message
    2014-05-06 12:54:43,229 - mylogger - WARNING - logger2 warning message
    2014-05-06 12:54:43,229 - mylogger - WARNING - logger2 warning message
    2014-05-06 12:54:43,230 - mylogger - ERROR - logger2 error message
    2014-05-06 12:54:43,230 - mylogger - ERROR - logger2 error message
    2014-05-06 12:54:43,231 - mylogger - CRITICAL - logger2 critical message
    2014-05-06 12:54:43,231 - mylogger - CRITICAL - logger2 critical message
    2014-05-06 12:54:43,232 - mylogger.child1 - WARNING - logger3 warning message
    2014-05-06 12:54:43,232 - mylogger.child1 - WARNING - logger3 warning message
    2014-05-06 12:54:43,232 - mylogger.child1 - WARNING - logger3 warning message
    2014-05-06 12:54:43,234 - mylogger.child1 - ERROR - logger3 error message
    2014-05-06 12:54:43,234 - mylogger.child1 - ERROR - logger3 error message
    2014-05-06 12:54:43,234 - mylogger.child1 - ERROR - logger3 error message
    2014-05-06 12:54:43,235 - mylogger.child1 - CRITICAL - logger3 critical message
    2014-05-06 12:54:43,235 - mylogger.child1 - CRITICAL - logger3 critical message
    2014-05-06 12:54:43,235 - mylogger.child1 - CRITICAL - logger3 critical message
    2014-05-06 12:54:43,237 - mylogger.child1.child2 - DEBUG - logger4 debug message
    2014-05-06 12:54:43,237 - mylogger.child1.child2 - DEBUG - logger4 debug message
    2014-05-06 12:54:43,237 - mylogger.child1.child2 - DEBUG - logger4 debug message
    2014-05-06 12:54:43,237 - mylogger.child1.child2 - DEBUG - logger4 debug message
    2014-05-06 12:54:43,239 - mylogger.child1.child2 - INFO - logger4 info message
    2014-05-06 12:54:43,239 - mylogger.child1.child2 - INFO - logger4 info message
    2014-05-06 12:54:43,239 - mylogger.child1.child2 - INFO - logger4 info message
    2014-05-06 12:54:43,239 - mylogger.child1.child2 - INFO - logger4 info message
    2014-05-06 12:54:43,240 - mylogger.child1.child2 - WARNING - logger4 warning message
    2014-05-06 12:54:43,240 - mylogger.child1.child2 - WARNING - logger4 warning message
    2014-05-06 12:54:43,240 - mylogger.child1.child2 - WARNING - logger4 warning message
    2014-05-06 12:54:43,240 - mylogger.child1.child2 - WARNING - logger4 warning message
    2014-05-06 12:54:43,242 - mylogger.child1.child2 - ERROR - logger4 error message
    2014-05-06 12:54:43,242 - mylogger.child1.child2 - ERROR - logger4 error message
    2014-05-06 12:54:43,242 - mylogger.child1.child2 - ERROR - logger4 error message
    2014-05-06 12:54:43,242 - mylogger.child1.child2 - ERROR - logger4 error message
    2014-05-06 12:54:43,243 - mylogger.child1.child2 - CRITICAL - logger4 critical message
    2014-05-06 12:54:43,243 - mylogger.child1.child2 - CRITICAL - logger4 critical message
    2014-05-06 12:54:43,243 - mylogger.child1.child2 - CRITICAL - logger4 critical message
    2014-05-06 12:54:43,243 - mylogger.child1.child2 - CRITICAL - logger4 critical message
    2014-05-06 12:54:43,244 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 12:54:43,244 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 12:54:43,244 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 12:54:43,244 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 12:54:43,244 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 12:54:43,246 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 12:54:43,246 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 12:54:43,246 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 12:54:43,246 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 12:54:43,246 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 12:54:43,247 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 12:54:43,247 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 12:54:43,247 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 12:54:43,247 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 12:54:43,247 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 12:54:43,249 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 12:54:43,249 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 12:54:43,249 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 12:54:43,249 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 12:54:43,249 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 12:54:43,250 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message
    2014-05-06 12:54:43,250 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message
    2014-05-06 12:54:43,250 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message
    2014-05-06 12:54:43,250 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message
    2014-05-06 12:54:43,250 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message

    先简单介绍一下,logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。

    Logger
    Logger是一个树形层级结构,输出信息之前都要获得一个Logger(如果没有显示的获取则自动创建并使用root Logger,如第一个例子所示)。
    logger = logging.getLogger()返回一个默认的Logger也即root Logger,并应用默认的日志级别、Handler和Formatter设置。
    当然也可以通过Logger.setLevel(lel)指定最低的日志级别,可用的日志级别有logging.DEBUG、logging.INFO、logging.WARNING、logging.ERROR、logging.CRITICAL。
    Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical()输出不同级别的日志,只有日志等级大于或等于设置的日志级别的日志才会被输出。

    我们看到程序中
    logger.debug('logger debug message')
    logger.info('logger info message')
    logger.warning('logger warning message')
    logger.error('logger error message')
    logger.critical('logger critical message')
    只输出了
    2014-05-06 12:54:43,222 - root - WARNING - logger warning message
    2014-05-06 12:54:43,223 - root - ERROR - logger error message
    2014-05-06 12:54:43,224 - root - CRITICAL - logger critical message
    从这个输出可以看出logger = logging.getLogger()返回的Logger名为root。这里没有用logger.setLevel()显示的为logger设置日志级别,所以使用默认的日志级别WARNIING,故结果只输出了大于等于WARNIING级别的信息。

    另外,我们明明通过logger1.setLevel(logging.DEBUG)将logger1的日志级别设置为了DEBUG,为何显示的时候没有显示出DEBUG级别的日志信息,而是从INFO级别的日志开始显示呢?原来logger1和logger2对应的是同一个Logger实例,只要logging.getLogger(name)中名称参数name相同则返回的Logger实例就是同一个,且仅有一个,也即name与Logger实例一一对应。在logger2实例中通过logger2.setLevel(logging.INFO)设置mylogger的日志级别为logging.INFO,所以最后logger1的输出遵从了后来设置的日志级别。
    logger1 = logging.getLogger('mylogger')
    logger1.setLevel(logging.DEBUG)
    logger2 = logging.getLogger('mylogger')
    logger2.setLevel(logging.INFO)
    为什么logger1、logger2对应的每个输出分别显示两次,logger3对应的输出显示3次,logger4对应的输出显示4次......呢?
    这是因为我们通过logger = logging.getLogger()显示的创建了root Logger,而logger1 = logging.getLogger('mylogger')创建了root Logger的孩子(root.)mylogger,logger2同样。
    logger3 = logging.getLogger('mylogger.child1')创建了(root.)mylogger.child1
    logger4 = logging.getLogger('mylogger.child1.child2')创建了(root.)mylogger.child1.child2
    logger5 = logging.getLogger('mylogger.child1.child2.child3')创建了(root.)mylogger.child1.child2.child3
    而孩子,孙子,重孙……既会将消息分发给他的handler进行处理也会传递给所有的祖先Logger处理。

    试着注释掉如下一行程序,观察程序输出
    #logger.addHandler(fh)  
    发现标准输出中每条记录对应两行(因为root Logger默认使用StreamHandler)
    2014-05-06 15:10:10,980 - mylogger - INFO - logger1 info message
    2014-05-06 15:10:10,980 - mylogger - INFO - logger1 info message
    2014-05-06 15:10:10,981 - mylogger - WARNING - logger1 warning message
    2014-05-06 15:10:10,981 - mylogger - WARNING - logger1 warning message
    2014-05-06 15:10:10,982 - mylogger - ERROR - logger1 error message
    2014-05-06 15:10:10,982 - mylogger - ERROR - logger1 error message
    2014-05-06 15:10:10,984 - mylogger - CRITICAL - logger1 critical message
    2014-05-06 15:10:10,984 - mylogger - CRITICAL - logger1 critical message
    ……
    而在文件输出中每条记录对应一行(因为我们注释掉了logger.addHandler(fh),没有对root Logger启用FileHandler)
    2014-05-06 15:10:10,980 - mylogger - INFO - logger1 info message
    2014-05-06 15:10:10,981 - mylogger - WARNING - logger1 warning message
    2014-05-06 15:10:10,982 - mylogger - ERROR - logger1 error message
    2014-05-06 15:10:10,984 - mylogger - CRITICAL - logger1 critical message

    孩子,孙子,重孙……可逐层继承来自祖先的日志级别、Handler、Filter设置,也可以通过Logger.setLevel(lel)、Logger.addHandler(hdlr)、Logger.removeHandler(hdlr)、Logger.addFilter(filt)、Logger.removeFilter(filt)。设置自己特别的日志级别、Handler、Filter。若不设置则使用继承来的值。

    Handler
    上述例子的输出在标准输出和指定的日志文件中均可以看到,这是因为我们定义并使用了两种Handler。
    fh = logging.FileHandler('/tmp/test.log') 
    ch = logging.StreamHandler()
    Handler对象负责发送相关的信息到指定目的地,有几个常用的Handler方法:
    Handler.setLevel(lel):指定日志级别,低于lel级别的日志将被忽略
    Handler.setFormatter():给这个handler选择一个Formatter
    Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象

    可以通过addHandler()方法为Logger添加多个Handler:
    logger.addHandler(fh)
    logger.addHandler(ch)


    有多中可用的Handler:

    logging.StreamHandler 可以向类似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息
    logging.FileHandler 用于向一个文件输出日志信息
    logging.handlers.RotatingFileHandler 类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建一个新的同名日志文件继续输出
    logging.handlers.TimedRotatingFileHandler 和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就自动创建新的日志文件
    logging.handlers.SocketHandler 使用TCP协议,将日志信息发送到网络。
    logging.handlers.DatagramHandler 使用UDP协议,将日志信息发送到网络。
    logging.handlers.SysLogHandler 日志输出到syslog
    logging.handlers.NTEventLogHandler 远程输出日志到Windows NT/2000/XP的事件日志 
    logging.handlers.SMTPHandler 远程输出日志到邮件地址
    logging.handlers.MemoryHandler 日志输出到内存中的制定buffer
    logging.handlers.HTTPHandler 通过"GET"或"POST"远程输出到HTTP服务器
    各个Handler的具体用法可查看参考书册:
    https://docs.python.org/2/library/logging.handlers.html#module-logging.handlers


    Formatter
    Formatter对象设置日志信息最后的规则、结构和内容,默认的时间格式为%Y-%m-%d %H:%M:%S。
    #定义Formatter
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    #为Handler添加Formatter
    fh.setFormatter(formatter)
    ch.setFormatter(formatter)
    Formatter参数中可能用到的格式化串参见上文(logging.basicConfig()函数format参数中可能用到的格式化串:)

    Filter
    限制只有满足过滤规则的日志才会输出。
    比如我们定义了filter = logging.Filter('a.b.c'),并将这个Filter添加到了一个Handler上,则使用该Handler的Logger中只有名字带a.b.c前缀的Logger才能输出其日志。

    取消下列两行程序的注释
    #filter = logging.Filter('mylogger.child1.child2')
    #fh.addFilter(filter)  
    标准输出中输出结果并没有发生变化,但日志文件输出中只显示了如下内容:
    2014-05-06 15:27:36,227 - mylogger.child1.child2 - DEBUG - logger4 debug message
    2014-05-06 15:27:36,227 - mylogger.child1.child2 - DEBUG - logger4 debug message
    2014-05-06 15:27:36,227 - mylogger.child1.child2 - DEBUG - logger4 debug message
    2014-05-06 15:27:36,227 - mylogger.child1.child2 - DEBUG - logger4 debug message
    2014-05-06 15:27:36,228 - mylogger.child1.child2 - INFO - logger4 info message
    2014-05-06 15:27:36,228 - mylogger.child1.child2 - INFO - logger4 info message
    2014-05-06 15:27:36,228 - mylogger.child1.child2 - INFO - logger4 info message
    2014-05-06 15:27:36,228 - mylogger.child1.child2 - INFO - logger4 info message
    2014-05-06 15:27:36,230 - mylogger.child1.child2 - WARNING - logger4 warning message
    2014-05-06 15:27:36,230 - mylogger.child1.child2 - WARNING - logger4 warning message
    2014-05-06 15:27:36,230 - mylogger.child1.child2 - WARNING - logger4 warning message
    2014-05-06 15:27:36,230 - mylogger.child1.child2 - WARNING - logger4 warning message
    2014-05-06 15:27:36,232 - mylogger.child1.child2 - ERROR - logger4 error message
    2014-05-06 15:27:36,232 - mylogger.child1.child2 - ERROR - logger4 error message
    2014-05-06 15:27:36,232 - mylogger.child1.child2 - ERROR - logger4 error message
    2014-05-06 15:27:36,232 - mylogger.child1.child2 - ERROR - logger4 error message
    2014-05-06 15:27:36,233 - mylogger.child1.child2 - CRITICAL - logger4 critical message
    2014-05-06 15:27:36,233 - mylogger.child1.child2 - CRITICAL - logger4 critical message
    2014-05-06 15:27:36,233 - mylogger.child1.child2 - CRITICAL - logger4 critical message
    2014-05-06 15:27:36,233 - mylogger.child1.child2 - CRITICAL - logger4 critical message
    2014-05-06 15:27:36,235 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 15:27:36,235 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 15:27:36,235 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 15:27:36,235 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 15:27:36,235 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 15:27:36,236 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 15:27:36,236 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 15:27:36,236 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 15:27:36,236 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 15:27:36,236 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 15:27:36,238 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 15:27:36,238 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 15:27:36,238 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 15:27:36,238 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 15:27:36,238 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 15:27:36,240 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 15:27:36,240 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 15:27:36,240 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 15:27:36,240 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 15:27:36,240 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 15:27:36,242 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message
    2014-05-06 15:27:36,242 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message
    2014-05-06 15:27:36,242 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message
    2014-05-06 15:27:36,242 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message
    2014-05-06 15:27:36,242 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message

    当然也可以直接给Logger加Filter。若为Handler加Filter则所有使用了该Handler的Logger都会受到影响。而为Logger添加Filter只会影响到自身。
    注释掉
    #fh.addFilter(filter) 
    并取消如下几行的注释
    #logger.addFilter(filter)
    #logger1.addFilter(filter)
    #logger3.addFilter(filter)
    #logger4.addFilter(filter)
    
    输出结果
    2014-05-06 15:32:10,746 - mylogger.child1.child2 - DEBUG - logger4 debug message
    2014-05-06 15:32:10,746 - mylogger.child1.child2 - DEBUG - logger4 debug message
    2014-05-06 15:32:10,746 - mylogger.child1.child2 - DEBUG - logger4 debug message
    2014-05-06 15:32:10,746 - mylogger.child1.child2 - DEBUG - logger4 debug message
    2014-05-06 15:32:10,748 - mylogger.child1.child2 - INFO - logger4 info message
    2014-05-06 15:32:10,748 - mylogger.child1.child2 - INFO - logger4 info message
    2014-05-06 15:32:10,748 - mylogger.child1.child2 - INFO - logger4 info message
    2014-05-06 15:32:10,748 - mylogger.child1.child2 - INFO - logger4 info message
    2014-05-06 15:32:10,751 - mylogger.child1.child2 - WARNING - logger4 warning message
    2014-05-06 15:32:10,751 - mylogger.child1.child2 - WARNING - logger4 warning message
    2014-05-06 15:32:10,751 - mylogger.child1.child2 - WARNING - logger4 warning message
    2014-05-06 15:32:10,751 - mylogger.child1.child2 - WARNING - logger4 warning message
    2014-05-06 15:32:10,753 - mylogger.child1.child2 - ERROR - logger4 error message
    2014-05-06 15:32:10,753 - mylogger.child1.child2 - ERROR - logger4 error message
    2014-05-06 15:32:10,753 - mylogger.child1.child2 - ERROR - logger4 error message
    2014-05-06 15:32:10,753 - mylogger.child1.child2 - ERROR - logger4 error message
    2014-05-06 15:32:10,754 - mylogger.child1.child2 - CRITICAL - logger4 critical message
    2014-05-06 15:32:10,754 - mylogger.child1.child2 - CRITICAL - logger4 critical message
    2014-05-06 15:32:10,754 - mylogger.child1.child2 - CRITICAL - logger4 critical message
    2014-05-06 15:32:10,754 - mylogger.child1.child2 - CRITICAL - logger4 critical message
    2014-05-06 15:32:10,755 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 15:32:10,755 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 15:32:10,755 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 15:32:10,755 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 15:32:10,755 - mylogger.child1.child2.child3 - DEBUG - logger5 debug message
    2014-05-06 15:32:10,757 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 15:32:10,757 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 15:32:10,757 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 15:32:10,757 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 15:32:10,757 - mylogger.child1.child2.child3 - INFO - logger5 info message
    2014-05-06 15:32:10,759 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 15:32:10,759 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 15:32:10,759 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 15:32:10,759 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 15:32:10,759 - mylogger.child1.child2.child3 - WARNING - logger5 warning message
    2014-05-06 15:32:10,761 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 15:32:10,761 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 15:32:10,761 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 15:32:10,761 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 15:32:10,761 - mylogger.child1.child2.child3 - ERROR - logger5 error message
    2014-05-06 15:32:10,762 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message
    2014-05-06 15:32:10,762 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message
    2014-05-06 15:32:10,762 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message
    2014-05-06 15:32:10,762 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message
    2014-05-06 15:32:10,762 - mylogger.child1.child2.child3 - CRITICAL - logger5 critical message

    发现root、mylogger、mylogger.child1的输出全部被过滤掉了。

    除了直接在程序中设置Logger,Handler,Filter,Formatter外还可以将这些信息写进配置文件中。

    例如典型的logging.conf

    [loggers]
    keys=root,simpleExample
    
    [handlers]
    keys=consoleHandler
    
    [formatters]
    keys=simpleFormatter
    
    [logger_root]
    level=DEBUG
    handlers=consoleHandler
    
    [logger_simpleExample]
    level=DEBUG
    handlers=consoleHandler
    qualname=simpleExample
    propagate=0
    
    [handler_consoleHandler]
    class=StreamHandler
    level=DEBUG
    formatter=simpleFormatter
    args=(sys.stdout,)
    
    [formatter_simpleFormatter]
    format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
    datefmt=
    

    程序可以这么写
    import logging  
    import logging.config  
      
    logging.config.fileConfig("logging.conf")    # 采用配置文件   
      
    # create logger   
    logger = logging.getLogger("simpleExample")  
      
    # "application" code   
    logger.debug("debug message")  
    logger.info("info message")  
    logger.warn("warn message")  
    logger.error("error message")  
    logger.critical("critical message")

    多模块使用logging
    logging模块保证在同一个python解释器内,多次调用logging.getLogger('log_name')都会返回同一个logger实例,即使是在多个模块的情况下。所以典型的多模块场景下使用logging的方式是在main模块中配置logging,这个配置会作用于多个的子模块,然后在其他模块中直接通过getLogger获取Logger对象即可。

    main.py:
    import logging  
    import logging.config  
      
    logging.config.fileConfig('logging.conf')  
    root_logger = logging.getLogger('root')  
    root_logger.debug('test root logger...')  
      
    logger = logging.getLogger('main')  
    logger.info('test main logger')  
    logger.info('start import module \'mod\'...')  
    import mod  
      
    logger.debug('let\'s test mod.testLogger()')  
    mod.testLogger()  
      
    root_logger.info('finish test...') 

    子模块mod.py:

    import logging  
    import submod  
      
    logger = logging.getLogger('main.mod')  
    logger.info('logger of mod say something...')  
      
    def testLogger():  
        logger.debug('this is mod.testLogger...')  
        submod.tst() 
    
    子子模块submod.py:
    import logging  
      
    logger = logging.getLogger('main.mod.submod')  
    logger.info('logger of submod say something...')  
      
    def tst():  
        logger.info('this is submod.tst()...')  


    
    
    展开全文
  • logging 模块的简单使用:

    千次阅读 2018-07-11 20:02:18
    import logging,os FILE = os.getcwd() 设置文件路径,默认是追加到文件中,不过可以设置filemode="w",为重写进去。 logging.basicConfig(filename=os.path.join(FILE,"dosubprocess.log"),file...

    配置输出日志到文件

    
    导入模块
    import logging,os
    FILE = os.getcwd()
    设置文件路径,默认是追加到文件中,不过可以设置filemode="w",为重写进去。
    logging.basicConfig(filename=os.path.join(FILE,"dosubprocess.log"),filemode="w",
                        format="%(levelname)s:%(message)s",level=logging.INFO)
                        
                        
                        

    可以在外面设置级别

    
    import logging
    logging.basicConfig(level="laowang")
    #必须调用getLOgger获得一个loggging对象后,才可以为他设置级别。
    log=logging.getLogger(__name__)
    #logging的属性,propagate,意思是是否消息是否层层上传。
    print(log.propagate)
    #设置logging对象的级别
    log.setLevel(logging.WARN)

    logging创建流handler,将信息显示到控制台,

    import logging,os
    logging.basicConfig(filename=os.path.join(os.getcwd(),"my_property.log"),
                        format="%(levelname)-10s %(asctime)-20s %(message)s",
                        datefmt="%m/%d/%Y %I:%M:%S",
                        level=logging.DEBUG,
                        filemode="w")
    
    console=logging.StreamHandler()
    console.setLevel(logging.INFO)
    formatter=logging.Formatter("%(levelname)-10s %(asctime)-20s %(message)s")
    console.setFormatter(formatter)
    logging.getLogger("").addHandler(console)
    
    '''
    快速入门
    基础知识
    日志的作用是跟踪,django项目中不可缺少。
    
    派出:
    
    控制台输出:print()
    
    报告事件,发生在一个程序的正常运行:logging.info() 或 logging.debug()
    
    发出警告关于一个特定的运行时事件:warnings.warn() 或 logging.warning()
    
    报告一个错误对于一个特定的运行时事件:异常处理
    
    报告一个错误当没有引发一个异常:logging.error()、logging.exception() 或 logging.critical()
    
    DEBUG:详细的信息,通常只出现在诊断问题上
    
    INFO:确认一切按预期运行
    
    WARNING:一个迹象表明,一些意想不到的事情发生了,或表明一些问题在不久的将来(例如。磁盘空间低”)。这个软件还能按预期工作
    
    ERROR:个更严重的问题,软件没能执行一些功能
    
    CRITICAL:一个严重的错误,这表明程序本身可能无法继续运行
    
    日志一共分成5个等级,从低到高分别是:DEBUG INFO WARNING ERROR CRITICAL。这5个等级,也分别对应5种打日志的方法: debug 、info 、warning 、error 、critical。
    
    默认的是WARNING,当在WARNING或之上时才被跟踪。
    有两种方式记录跟踪,一种输出控制台,另一种是记录到文件中,如日志文件。
    
    日志一共分成5个等级,从低到高分别是:DEBUG INFO WARNING ERROR CRITICAL。这5个等级,也分别对应5种打日志的方法: debug 、info 、warning 、error 、critical。
    默认的是WARNING,当在WARNING或之上时才被跟踪。
    有两种方式记录跟踪,一种输出控制台,另一种是记录到文件中,如日志文件
    
    '''
    
    '''
    简单日志操作
    写入一个文件里面:
    '''
    #logging to file
    # import os
    # import logging
    #
    # # with open("log.txt","w",encoding="utf-8") as f:
    # #     f.write("")
    #
    # FILE =os.getcwd()
    # logging.basicConfig(filename=os.path.join(FILE,"log.txt"),level=logging.DEBUG)
    # logging.debug("写进去")
    # logging.info("滚进去")
    # logging.warning("也滚进去")
    '''
    来学习一些日志组件以及一些高级部分。
    日志组件包括:loggers、handlers、filters、formatters。
    
    Logger 对象扮演了三重角色。
    首先,它暴露给应用几个方法以便应用可以在运行时写log;
    其次,Logger对象按照log信息的严重程度或者
    根据filter对象来决定如何处理log信息(默认的过滤功能);
    最后,logger还负责把log信息传送给相关的loghandlers。
    
    Handler对象负责分配合适的log信息(基于log信息的严重 程度)到handler指定的目的地。
    Logger对象可以用addHandler()方法添加零个或多个handler对象到它自身。
    一个常见的场景是,一个应用可能希望把所有的log信息都发送到一个log文件中去,
    所有的error级别以上的log信息都发送到stdout,
    所有critical 的log信息通过email发送。
    这个场景里要求三个不同handler处理,每个handler负责把特定的log信息发送到特定的地方。
    
    filter:细致化,选择哪些日志输出
    
    format:设置显示格式
    
    '''
    '''
    ogging.basicConfig ( [ * * kwargs ] )
    该语句是日志模块配置基本信息。kwargs 支持如下几个关键字参数:
    
    filename :日志文件的保存路径。如果配置了些参数,将自动创建一个FileHandler作为Handler;
    
    filemode :日志文件的打开模式。 默认值为’a’,表示日志消息以追加的形式添加到日志文件中。如果设为’w’, 那么每次程序启动的时候都会创建一个新的日志文件;
    
    format :设置日志输出格式;
    
    datefmt :定义日期格式;
    
    level :设置日志的级别.对低于该级别的日志消息将被忽略;
    
    stream :设置特定的流用于初始化StreamHandler。
    
    '''
    '''
    logging.getLogger ( [ name ] )
    创建Logger对象。日志记录的工作主要由Logger对象来完成。
    
    在调用getLogger时要提供Logger的名称(注:多次使用相同名称 来调用getLogger,
    返回的是同一个对象的引用。),Logger实例之间有层次关系,这些关系通过Logger名称来体现,如
    '''
    # import logging
    
    '''命名'''
    # log2=logging.getLogger("BeginMan") #生成一个日志对象
    # print(log2)#<logging.Logger object at 0x00000000026D1710>
    '''无名'''
    # log3=logging.getLogger()
    # print(log3)
    
    '''最好的方式'''
    # log = logging.getLogger(__name__)#_name__ is the module’s name in the Python package namespace.
    # print(log)
    # print(__name__)
    '''
    Logger对象,
    有如下属性和方法:
    Logger.propagate
    
    具体参考:http://docs.python.org/2.7/library/logging.html Logger.setLevel(lvl) 
    ——————– 设置日志的级别。对于低于该级别的日志消息将被忽略。
    
    '''
    # import logging
    # import os
    # logging.basicConfig(format="%(levelname)s,%(message)s",filename=os.path.join(os.getcwd(),"log.txt"),level=logging.DEBUG)
    # log=logging.getLogger("root.set") #Logger 对象
    # print(log.propagate)
    #
    # log.setLevel(logging.WARN) #日志记录级别为WARNNING
    # log.info("msg")
    # log.debug("msg")
    # log.warning("msg")
    # log.error("msg")
    #
    '''
    Handler对象、Formatter对象、Filter对象、Filter对象
    
    '''
    
    # import logging
    # import os
    # '''logger'''
    # l=logging.Logger("root")  #创建logger对象
    # log=logging.getLogger("root")  #通过logging.getlogger创建对象
    #
    # print(l)
    # print(log)
    #
    # '''Handler'''
    # handler=logging.Handler() #创建Handler对象
    # handler.__init__(logging.DEBUG)  #通过设置levell劳初始刷handler实例
    # handler.createLock()#初始化一个县城索,可以用来序列化,访问底层i/ogongneng,这可鞥不是县城安全的
    # handler.acquire() #获取线程锁,通过handler.createLock()
    # handler.release() #释放获得的县城索
    # handler.setLevel(logging.DEBUG) #设置临界值,如果logging信息级别小于他的责被忽视
    # handler.setFormatter("%(levelname)s,%(message)s") #设置格式
    # handler.addFilter(filter)#
    '''
    3.将日志同时输出到文件和屏幕
    '''
    # 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="myapp.log",
    #                     filemode="w")
    # 定义一个StreamHandler,将INFO级别或更高的日志信息打印到标准错误,
    # 并将其添加到当前的日志处理对象
    # console=logging.StreamHandler()
    # console.setLevel(logging.INFO)
    # formatter=logging.Formatter("%(name)-12s:%(levelname)-8s %(message)s")
    # console.setFormatter(formatter)
    # logging.getLogger("").addHandler(console)
    #
    # logging.debug("This is debug message")
    # logging.info("This is info message ")
    # logging.warning("Thsi is warning message")
    
    
    # level: 设置日志级别,默认为logging.WARNING
    # stream: 指定将日志的输出流,
    # 可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,
    # 当stream和filename同时指定时,stream被忽略
    
    '''
    . 每一个Logger实例的level如同入口,让水流进来,如果这个门槛太高,信息就进不来。例如log2.info('log3 info'),如果log2定义的级别高于info级别,就不会又信息通过log2
    
    2. 如果level没有设置,就用父logger的,如果父logger的level也没有设置,继续找父的父的,最终找到root上,如果root设置了就用它的,如果root没有设置,root的默认值是WARNING
    
    3.消息传递流程:
    
    在某个logger上产生某种级别的信息,首先和logger的level检查,如果消息level低于logger的EffectiveLevl有效级别,消息丢弃,不会再向父logger传递该消息。如果通过(大于等于)检查后,则把消息交给logger所有的handler处理,每一个handler需要和自己level比较来决定是否处理。
    
     
    
    如果没有一个handler,或者消息已经被handler处理过了,则需要通过本logger的propagate属性是否为True,Ture则把这个消息会继续发给父Logger,当前Logger的父Logger称为当前Logger,新的Logger的所有Handler继续处理消息。
    
    4. logger实例初始的propagate属性为True,即允许想父logger传递消息
    
    5. logger.basicConfig
    
    如果root没有handler,就默认创建一个StreamHandler,如果设置了filename,就创建一个FileHandler。如果设置了format参数,就会用它生成一个formatter对象,并把这个formatter加入到刚才创建的handler上,然后把这些handler加入到root.handlers列表上。level 是设置给root.logger的。
    
    如果root.handlers列表不为空,logging.basicConfig的调用什么都不做。
    
    
    
    标准库里面的logging模块,在前面学习线程安全时曾用来解决print被打断的问题,这里会介绍logging模块的功能。
    
    logging模块是线程安全的,不需要客户做任何特殊的工作。它通过使用线程锁实现了这一点; 有一个锁来序列化访问模块的共享数据,
    每个处理程序还创建一个锁来序列化访问其底层 I/O。
    
    
    使用工厂方法返回一个Logger实例。
    
    logging.getLogger([name=None])
    
     指定name,返回一个名称为name的Logger实例。如果再次使用相同的名字,是实例化一个对象。未指定name,返回Logger实例,名称是root,即根Logger。
    
    Logger是层次结构的,使用 '.' 点号分割,如'a'、'a.b'或'a.b.c.d','a'是'a.b'的父parent,a.b是a的子child。对于foo来说,名字为foo.bar、foo.bar.baz、foo.bam都是foo的后代。
    
    '''
    
    # import logging
    # DATEFMT="[%Y-%m-%d %H:%M:%s]"
    # FORMAT="%(asctime)s %(thread)d %(message)s"
    # logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt=DATEFMT,filename="log.txt")
    #
    # root=logging.getLogger()
    # print(root.name,type(root),root.parent,id(root))
    #
    # logger=logging.getLogger(__name__)
    # print(logger.name,type(logger),id(logger),id(logger.parent))
    #
    # logger1=logging.getLogger(__name__+".ok")
    # print(logger1.name,type(logger1),id(logger1),id((logger1.parent)))
    #
    # print(logger1.parent,id(logger.parent))
    '''
    子child的级别设置,不影响父parent的级别:
    '''
    # import logging
    #
    # FORMAT="%(asctime)s %(thread)d %(message)s"
    # logging.basicConfig(level=logging.WARNING,format=FORMAT,datefmt="[%Y-%m-%d %H:%M:%S]")
    #
    # root=logging.getLogger()
    # print(1,root,id(root))
    # root.info("my root")
    #
    # loga=logging.getLogger(__name__)
    # print(2,id(loga),id(loga.parent))
    # print(3,loga.getEffectiveLevel())
    #
    # loga.warning("before")
    # loga.setLevel(28)
    # print(4,loga.getEffectiveLevel)
    # loga.info("after")
    # loga.warning("after")
    '''
    Handler
    
      StreamHandler #不指定使用sys.strerr
    
        FileHandler #文件
    
        _StderrHandler #标准输出
    
      NullHandler #什么都不做
    
    logger实例,如果设置了level,就用它和信息的级别比较,否则,继承最近的祖先的level。
    
    '''
    
    # import logging
    # FORMAT ="%(asctime)s %(thread)d %(message)s"
    # logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt="[%Y-%m-%d %H:%M:%S]")
    #
    # root=logging.getLogger()
    # print("root",root.getEffectiveLevel())
    #
    # log1=logging.getLogger("s")
    # log1.setLevel(logging.ERROR)
    # print("log1:",log1.getEffectiveLevel())
    # log1.error("log1 error")
    #
    # log2=logging.getLogger("s.s1")
    # log2.setLevel(logging.WARNING)
    # print("log2",log2.getEffectiveLevel())
    # log2.warning("log2 warning")
    #
    #
    
    '''
    Handler:
    
    Handler控制日志信息的输出目的地,可以是控制台、文件。
    
    可以单独设置level
    
    可以单独设置格式
    
    可以设置过滤器
    
     
    
    Handler
    
      StreamHandler #不指定使用sys.strerr
    
        FileHandler #文件
    
        _StderrHandler #标准输出
    
      NullHandler #什么都不做
    
    '''
    # import logging
    #
    # FORMAT ="%(asctime)s %(thread)d %(message)s"
    # logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt="[%Y-%m-%d %H:%M:%S]")
    #
    # root=logging.getLogger()
    # print("root:",root.getEffectiveLevel())
    #
    # log1=logging.getLogger("s")
    # log1.setLevel(logging.ERROR)
    # print("log1:",log1.getEffectiveLevel())
    # log1.error("log1.error")
    #
    # log2=logging.getLogger("s.s1")
    # log2.setLevel(logging.WARNING)
    # print("log2:",log2.getEffectiveLevel())
    # log2.warning("log2.warning")
    
    '''
    loggerLevel --> FilterConditions --> HandlerLevel --> 
    父LoggerFilter --> 父LoggerHandler --> RootHandler --> 标准输出或记录到日志:
    
    
    '''
    
    import logging,datetime
    
    FORMAT="%(asctime)s %(thread)s %(message)s"
    logging.basicConfig(level=logging.WARNING,format=FORMAT,datefmt="[%Y-%m-%d %H:%M:%S]")
    
    "--------------root----------------------"
    root=logging.getLogger()
    print(1,root.getEffectiveLevel())
    "---------------------log1---------------------"
    log1=logging.getLogger("s")
    log1.setLevel(logging.ERROR)
    print(2,log1.getEffectiveLevel())
    
    h1=logging.FileHandler("h1.log")
    h1.setLevel(logging.INFO)
    log1.addHandler(h1)
    
    "----------------log2-----------"
    log2=logging.getLogger("s.s2")
    log2.setLevel(logging.WARNING)
    print(3,log2.getEffectiveLevel())
    
    h2=logging.FileHandler("h2.log")
    h2.setLevel(logging.WARNING)
    f2=logging.Filter("s.s3")
    h2.addFilter(f2)
    log2.addHandler(h2)
    
    log2.warning("4,log2 warning---{}".format(datetime.datetime.now()))
    如果要实现多个模块用一个定义好的logging模式,可以定义一个模板,
    然后各个模块在导入的时候,调用一下,就好啦。
    文件一  log1
    import logging
    from string import Template
    
    def lo():
        logging.info("log1--------------")
        logging.warning("name:%s msg:%s","BeginMan","Hi")
        logging.warning("name:%s msg:%s"%("BeginMan","Hi"))
        logging.warning("name:{0} mag:{1}".format("b而过inMan","HI"))
        msg=Template("name:$who msg:$what")
        logging.warning(msg.substitute(who="BeginMan",what="Hi"))
        
    文件log2    
    import logging
    import os
    FIFE  =os.getcwd()
    import log1
    
    
    def main():
        logging.basicConfig(filename=os.path.join(FIFE,"log1.txt"),level=logging.INFO)
        logging.info("start-------------")
        log1.lo()
        logging.info("end---------")
    if __name__=="__main__":
        main()
    
    

    展开全文
  • logging模块

    2019-06-11 16:41:11
    日志级别 日志级别Level 数值 CRITICAL 50 ERROR 40 WARNING 30,默认级别 INFO 20 DEBUG 10 NOTSET 0 日志级别指的是产生日志的事件的严重程度 设置一个级别后,严重程度低于设置值的日志......
    日志级别
    日志级别Level 数值
    CRITICAL 50
    ERROR 40
    WARNING 30,默认级别
    INFO 20
    DEBUG 10
    NOTSET 0

    日志级别指的是产生日志的事件的严重程度
    设置一个级别后,严重程度低于设置值的日志消息将被忽略
    debug(),info(),warning(),error()和critical()方法

    格式字符串
    属性名 格式 描述
    日志消息内容 %(message)s The logged message,computed as msg %args.当调用Formatter.format()时设置
    asctime %(asctime)s 创建LogRecord时的可读时间。默认情况下,它的格式为“2003-07-08 16:49:45,896”(逗号后面的数字是毫秒部分的时间)
    函数名 %(funcName)s 日志调用所在的函数名
    日志级别名称 %(levelname)s 消息的级别名称’DEBUG’,‘INFO’,‘WARNING’,‘ERROR’,‘CRITICAL’
    日记级别数值 %(levelno)s 消息的级别数字,对应DEBUG,INFO,WARNING,ERROR,CRITICAL
    行号 %(lineno)d 日志调用所在的源码行号
    模块 %(module)s 模块(filename的名字部分)
    进程ID %(process)d 进程ID
    线程ID %(thread)d 线程ID
    进程名称 %(processName)s 进程名
    线程名称 %(threadName)s 线程名
    logger名称 %(name)s logger名
    默认级别
    #默认为WARRING
    import logging
    FORMAT="%(asctime)s\t Thread info: %(thread)d %(threadName)s %(message)s " \
           "simple level: %(levelno)d %(levelname)s"
    logging.basicConfig(format=FORMAT)
    logging.info(20)
    logging.warning(10)
    

    在这里插入图片描述

    构建消息
    import logging
    FORMAT="%(asctime)s\t Thread info: %(thread)d %(threadName)s %(message)s " \
           "simple level: %(levelno)d %(levelname)s"
    logging.basicConfig(format=FORMAT,level=logging.INFO)
    logging.info(20)
    logging.warning(10)
    
    字符串扩展

    如果需要输出其他内容可以使用extra扩展

    import logging
    FORMAT="%(asctime)s\t Thread info: %(thread)d %(threadName)s %(message)s " \
           "simple level: %(levelno)d %(levelname)s~~~~~~~%(school)s"
    logging.basicConfig(format=FORMAT,level=logging.INFO)
    d={'school':'university'}
    logging.info(20,extra=d)
    logging.warning(10,extra=d)
    

    在这里插入图片描述

    修改日期和输出到文件
    import logging
    logging.basicConfig(format='%(asctime)s %(message)s',datefmt="%Y/%m/%d %H:%M:%S",filename='C:/Users/ASUS/temp/o.txt')
    logging.warning('this')
    logging.warning('is')
    logging.warning('sssssss')
    

     v
    在这里插入图片描述

    Logger类

    在logging模块中,顶层代码中有

    在这里插入图片描述
    logging模块加载的时候,会创建一个全局对象root,它是一个RootLogger实例,即root logger。根Logger对象的默认等级为WARNING。
    RootLogger类继承自Logger类
    类Logger初始化方法签名是(name,level=0)
    类RootLogger初始化方法签名(level),本质上调用的是logger.init(self,“root”,WARNING)
    调用logging,basicConfig来调整级别,就是对这个根Logger的级别进行修改

    构造

    Logger实例的构建,使用Logger类也行,推荐使用getLogger函数

    import logging
    from logging import Manager,Logger
    Logger.manager=Manager(Logger.root)
    def getLogger(name=None):
        if name:
            return Logger.manager.getLogger(name)
        else:
            return root
    

    使用工厂方法返回一个Logger实例
    指定name,返回一个名称为name的Logger实例,如果再次使用相同的名字,返回同一个实例,背后使用一个字典保证同一个名称返回同一个Logger实例
    未指定name,返回根Logger实例。

    import logging
    a=logging.Logger('hello',20)
    b=logging.Logger('hello',30)
    print(a,id(a))
    print(b,id(b))
    
    c=logging.getLogger('hello')
    print(c,id(c))
    d=logging.getLogger('hello')
    print(d,id(d))
    
    层次结构

    Logger是层次结构的,使用.点号分割。

    import logging
    root=logging.root
    print(root,id(root))
    root=logging.getLogger()
    print(root,id(root))
    print(root.name,type(root),root.parent)
    
    parent=logging.getLogger(__name__)
    print(parent.name,type(parent),id(parent.parent),id(parent),parent.parent,parent)
    
    child=logging.getLogger("{}{}".format(__name__,'.child'))
    print(child.name,type(child),id(child.parent),id(child))
    

    在这里插入图片描述

    Level级别设置

    每一个logger实例都有级别设置

    import logging
    FORMAT="%(asctime)s\t Thread info: %(thread)d %(threadName)s %(message)s %(levelname)s"
    logging.basicConfig(format=FORMAT,level=logging.INFO)
    logger=logging.getLogger(__name__)
    print(logger.name,type(logging),logger.level)
    logger.info('1 info')
    print(logger.getEffectiveLevel())
    
    logger.setLevel(28)
    print(logger.getEffectiveLevel(),logger.level,'~~~~~~~~~``')
    # INFO的级别是20,所以不会输出
    logger.info('2 info')
    
    logger.setLevel(42)
    logger.warning('3 warning')
    logger.error('4 error')
    logger.critical('5 critical')
    
    root=logging.getLogger()
    root.info('6 root info')
    

    在这里插入图片描述
    每一个logger实例,都有一个等效的level
    logger对象可以在创建后动态的修改自己的level
    等效level决定这logger实例能输出什么级别信息

    Handler

    Handler控制日志信息的输出目的地,可以是控制台、文件

    • 可以单独设置level
    • 可以单独设置格式
    • 可以设置过滤器

    Handler类层次

    • Handler
      • StreamHandler #不指定使用sys.stderr
        • FileHandler #文件
        • _StderrHandler#标准输出
      • NullHandler#什么都不做
        日志输出其实是Handler做的,也就是真正起作用的是Handler
        在logging.basicConfig函数中:
                if handlers is None:
                    filename = kwargs.pop("filename", None)
                    mode = kwargs.pop("filemode", 'a')
                    if filename:
                        h = FileHandler(filename, mode)
                    else:
                        stream = kwargs.pop("stream", None)
                        h = StreamHandler(stream)
                    handlers = [h]
    

    如果设置文件名,则为根Logger加一个输出到文件的FileHandler;如果没有设置文件名,则为根Logger加一个StreamHandler,默认输出到sys.stderr。
    也就是说,根logger一定会至少有一个handler的。

    import logging
    FORMAT='%(asctime)s %(name)s %(message)s'
    logging.basicConfig(format=FORMAT,level=logging.INFO)
    
    logger=logging.getLogger('test')
    print(logger.name,type(logger))
    logger.info('line 1')
    
    handler=logging.FileHandler('C:/Users/ASUS/temp/o.txt','w')
    logger.addHandler(handler)
    logger.info('line 2')
    

    在这里插入图片描述

    日志流

    level继承

    import logging
    logging.basicConfig(format="%(asctime)s %(name)s [%(message)s]")
    
    log1=logging.getLogger('s')
    print(log1.level,log1.getEffectiveLevel())
    log1.info('1 info')
    
    log2=logging.getLogger('s.s1')
    print(log2.level,log2.getEffectiveLevel())
    log2.info('2.info')
    print('~~~~~~~~~~~~')
    
    log1.setLevel(20)
    log1.info('3 info')
    print(log1.level,log1.getEffectiveLevel())
    print(log2.level,log2.getEffectiveLevel())
    log2.info('4.info')
    

    在这里插入图片描述
    logger实例
    如果不设置level,则初始level为0
    如果设置了level,就优先使用自己的level,否则,继承最近的祖先的level。
    信息是否能够从该logger实例上输出,就要看当前的函数的level是否大于等于logger的有效level。

    继承关系及信息传递
    • 每一个Logger实例会有一个level,如果输出等级小于这个level,无法输出

    • 如果level没有设置,就用父logger的,如果父logger的level没有设置,继续找父的父,最终找到root上,如果root设置了就用root的,如果没有设置,采用默认值WARNING。

    • 消息传递流程

      • 如果消息在某一个logger对象上产生,这个对象就是当前logger,首先消息level要和当前logger的EffectiveLevel比较,如果低于当前logger的EffectiveLevel,则流程结束,否则生成log记录。
      • 日志记录会交给当前logger的所有handler处理,记录还要和每一个handler的级别分别比较,低的不处理,否则按照handler输出日志记录
      • 当前logger的所有handler处理完后,就要看自己的propagate属性,如果是True表示向父logger传递这个日志记录,否则流程到此结束
      • 如果日志记录传递到了父logger,不需要和父logger的level比较,而是直接交给父的所有handler,父logger成为当前logger,直到当前logger的父logger是None退出。
    • logger实例初始的propagate属性为True,即允许向父logger传递消息

    • logging.basicConfig函数
      如果root没有handler,就默认创建一个StreamHandler,如果设置了filename,就创建一个FileHandler。如果设置了format参数,就会用它生成一个Formatter对象,否则会生成缺省Formatter,并把这个formatter加入到刚才创建的handler,然后把这些handler加入到root.handlters列表上,level是设置给root loggre的,如果root.handler列表不为空,logging.basicConfig的调用什么都不做。

    展开全文
  • logging大全

    2019-04-10 19:04:37
    python logging 替代print 输出内容到控制台和重定向到文件 在写程序的时候,尤其是大型的程序,在程序中加入日志系统是必不可少的,它能记录很多的信息。刚刚接触python的时候肯定都在用print来输出信息,这样是最...
  • logging日志的四个等级和使用

    万次阅读 2019-08-11 16:14:16
    1. logging日志的介绍 在现实生活中,记录日志非常重要,比如:银行转账时会有转账记录;飞机飞行过程中,会有个黑盒子(飞行数据记录器)记录着飞机的飞行过程,那在咱们python程序中想要记录程序在运行时所产生的日...
  • logging

    2019-07-16 21:58:20
    Python 使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适:  logger提供了应用程序可以直接使用的接口;  handler将(logger创建的)日志记录发送到合适的目的输出;  filter提供了细度设备来...
  • logging日志

    2019-08-03 19:32:47
    遇到python不懂的问题,可以加Python学习交流qun 688244617一起学习交流,还有零基础入门的学习资料和大量干货哦 1.在settings配置文件中配置以下文件: 定义三种日志输出格式 开始 standard_format = ‘[%(asctime)...
  • logging模块(日志模块)

    千次阅读 2018-10-17 11:31:41
    四、logging模块的Formatter,Handler,Logger,Filter对象 五、Logger与Handler的级别 六、Logger的继承(了解) 七、应用 django的配置 一、日志级别 import logging logging.debug('调试debug') #...
  • python 日志 logging模块(详细解析)

    万次阅读 多人点赞 2019-05-31 09:51:08
    1 基本使用 转自:...配置logging基本的设置,然后在控制台输出日志, import logging logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(name)s - %(...
  • springboot日志配置 logging.path logging.file 注意事项 可能有些小伙伴会同时配置 logging.path 和 logging.file,但是又发现其中一个不生效。 官方文档中有这么一句: If you want to write log files in ...
  • python logging.info在终端没输出

    万次阅读 2018-05-24 14:47:03
    问题描述:在pyhton脚本中logging.info("hello world")希望输出'hello world',但是在终端没有输出 解决方法: 在文件开始的地方添加以下内容: logging.getLogger().setLevel(logging.INFO)
  • Spring的各版本jar包下载地址 http://repo.spring.io/release/org/springframework/spring/ springframework下载地址 ... ...common-logging.jar包下载地址及步骤 http://commons.apac...
  • SSM框架项目启动发现启动不起来,反而控制台无限输出:Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter. ,这个错误只有在和Spring集成的情况下才会出现。 每次只要出现这...
  • logging 模块:记录日志 logging 模块可以用来记录日志: import logging logging 的日志类型有以下几种: logging.critical(msg) logging.error(msg) logging.warning(msg) logging.info(msg) logging.debug(msg)...
  • 当xml映射器中与实体类映射不正确,或者sql有其他错误时,会出现这种情况... 我的情况是:sql的唯一标识 id忘记加引号了...
  • python logging模块的多文件应用

    万次阅读 2015-11-20 10:14:13
    本文对logging进一步封装,展示如何在一个程序中使用logging模块打印两个log文件来记录不同类型的信息。 注意logging模块是线程安全的,可以在多线程环境中使用。 完整的代码 #!/usr/bin/env python2.7 # -*- ...
  • Py之logginglogging的简介、安装、使用方法之详细攻略 目录 logging的简介 logging的安装 logging的使用方法 logging的简介 Python引入了logging模块,是用来记录我们想要的信息。 1、logging ...
  • commons-logging的使用

    万次阅读 2016-02-26 11:00:53
    简介 commons-logging是Apache commons类库中的一员。Apache commons类库是一个通用的类库,提供了基础的功能,比如说commons-...commons-logging能够选择使用Log4j还是JDK Logging,但是他不依赖Log4j,JD
  •  Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter 致使springboot不能正常运行。。   解决之前遇到的情况类似于:  spirngboot框架不能正常运行,bean包不能正确配置...
1 2 3 4 5 ... 20
收藏数 353,714
精华内容 141,485
关键字:

logging