• logging日志模块


       一、日志级别

    CRITICAL = 50 #FATAL = CRITICAL
    ERROR = 40
    WARNING = 30 #WARN = WARNING
    INFO = 20
    DEBUG = 10
    NOTSET = 0 #不设置

    二、默认级别为warning,默认打印到终端
     1 import logging
     2 
     3 logging.debug('调试debug')
     4 logging.info('消息info')
     5 logging.warning('警告warn')
     6 logging.error('错误error')
     7 logging.critical('严重critical')
     8 
     9 '''
    10 WARNING:root:警告warn
    11 ERROR:root:错误error
    12 CRITICAL:root:严重critical
    13 '''
    相应级别

    三、为logging模块指定全局配置,针对所有logger有效,控制打印到文件中

     1 可在logging.basicConfig()函数中通过具体参数来更改logging模块默认行为,可用参数有
     2 filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
     3 filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
     4 format:指定handler使用的日志显示格式。 
     5 datefmt:指定日期时间格式。 
     6 level:设置rootlogger(后边会讲解具体概念)的日志级别 
     7 stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
     8 
     9 
    10 
    11 #格式
    12 %(name)s:Logger的名字,并非用户名,详细查看
    13 
    14 %(levelno)s:数字形式的日志级别
    15 
    16 %(levelname)s:文本形式的日志级别
    17 
    18 %(pathname)s:调用日志输出函数的模块的完整路径名,可能没有
    19 
    20 %(filename)s:调用日志输出函数的模块的文件名
    21 
    22 %(module)s:调用日志输出函数的模块名
    23 
    24 %(funcName)s:调用日志输出函数的函数名
    25 
    26 %(lineno)d:调用日志输出函数的语句所在的代码行
    27 
    28 %(created)f:当前时间,用UNIX标准的表示时间的浮 点数表示
    29 
    30 %(relativeCreated)d:输出日志信息时的,自Logger创建以 来的毫秒数
    31 
    32 %(asctime)s:字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
    33 
    34 %(thread)d:线程ID。可能没有
    35 
    36 %(threadName)s:线程名。可能没有
    37 
    38 %(process)d:进程ID。可能没有
    39 
    40 %(message)s:用户输出的消息
    41 
    42  
    43 
    44 logging.basicConfig()
    详细格式
     1 #======介绍
     2 可在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有
     3 filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
     4 filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
     5 format:指定handler使用的日志显示格式。
     6 datefmt:指定日期时间格式。
     7 level:设置rootlogger(后边会讲解具体概念)的日志级别
     8 stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
     9 
    10 
    11 format参数中可能用到的格式化串:
    12 %(name)s Logger的名字
    13 %(levelno)s 数字形式的日志级别
    14 %(levelname)s 文本形式的日志级别
    15 %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
    16 %(filename)s 调用日志输出函数的模块的文件名
    17 %(module)s 调用日志输出函数的模块名
    18 %(funcName)s 调用日志输出函数的函数名
    19 %(lineno)d 调用日志输出函数的语句所在的代码行
    20 %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
    21 %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
    22 %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
    23 %(thread)d 线程ID。可能没有
    24 %(threadName)s 线程名。可能没有
    25 %(process)d 进程ID。可能没有
    26 %(message)s用户输出的消息
    27 
    28 
    29 
    30 
    31 #========使用
    32 import logging
    33 logging.basicConfig(filename='access.log',
    34                     format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
    35                     datefmt='%Y-%m-%d %H:%M:%S %p',
    36                     level=10)
    37 
    38 logging.debug('调试debug')
    39 logging.info('消息info')
    40 logging.warning('警告warn')
    41 logging.error('错误error')
    42 logging.critical('严重critical')
    43 
    44 
    45 
    46 
    47 
    48 #========结果
    49 access.log内容:
    50 2018-04-18 10:32:17 AM - root - DEBUG -test:  调试debug
    51 2018-04-18 10:32:17 AM - root - INFO -test:  消息info
    52 2018-04-18 10:32:17 AM - root - WARNING -test:  警告warn
    53 2018-04-18 10:32:17 AM - root - ERROR -test:  错误error
    54 2018-04-18 10:32:17 AM - root - CRITICAL -test:  严重critical
    55 
    56 part2: 可以为logging模块指定模块级的配置,即所有logger的配置
    详细格式

     四、logging模块的Logger,Filter ,Handlerr, Formatter四个对象

    #logger:产生日志的对象
    
    #Filter:过滤日志的对象(基本不用)
    
    #Handler:接收日志然后控制打印到不同的地方,FileHandler用来打印到文件中,StreamHandler用来打印到终端
    
    #Formatter对象:可以定制不同的日志格式对象,然后绑定给不同的Handler对象使用,以此来控制不同的Handler的日志格式
    
     1 '''
     2 critical=50
     3 error =40
     4 warning =30
     5 info = 20
     6 debug =10
     7 '''
     8 
     9 
    10 import logging
    11 
    12 #1、logger对象:负责产生日志,然后交给Filter过滤,然后交给不同的Handler输出
    13 logger=logging.getLogger(__file__)
    14 
    15 #2、Filter对象:不常用,略
    16 
    17 #3、Handler对象:接收logger传来的日志,然后控制输出
    18 h1=logging.FileHandler('t1.log') #打印到文件
    19 h2=logging.FileHandler('t2.log') #打印到文件
    20 h3=logging.StreamHandler() #打印到终端
    21 
    22 #4、Formatter对象:日志格式
    23 formmater1=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
    24                     datefmt='%Y-%m-%d %H:%M:%S %p',)
    25 
    26 formmater2=logging.Formatter('%(asctime)s :  %(message)s',
    27                     datefmt='%Y-%m-%d %H:%M:%S %p',)
    28 
    29 formmater3=logging.Formatter('%(name)s %(message)s',)
    30 
    31 
    32 #5、为Handler对象绑定格式
    33 h1.setFormatter(formmater1)
    34 h2.setFormatter(formmater2)
    35 h3.setFormatter(formmater3)
    36 
    37 #6、将Handler添加给logger并设置日志级别
    38 logger.addHandler(h1)
    39 logger.addHandler(h2)
    40 logger.addHandler(h3)
    41 logger.setLevel(10)
    42 
    43 #7、测试
    44 logger.debug('debug')
    45 logger.info('info')
    46 logger.warning('warning')
    47 logger.error('error')
    48 logger.critical('critical')
    定制日志的流程(用下面的格式就行,这个太复杂)

    五、Logger与Handler的级别

      logger是第一级过滤,然后才能到handler,我们可以给logger和handler同时设置level,但是需要注意的是logger<handler(级别)

     1 Logger is also the first to filter the message based on a level — if you set the logger to INFO, and all handlers to DEBUG, you still won't receive DEBUG messages on handlers — they'll be rejected by the logger itself. If you set logger to DEBUG, but all handlers to INFO, you won't receive any DEBUG messages either — because while the logger says "ok, process this", the handlers reject it (DEBUG < INFO).
     2 
     3 
     4 
     5 #验证
     6 import logging
     7 
     8 
     9 form=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
    10                     datefmt='%Y-%m-%d %H:%M:%S %p',)
    11 
    12 ch=logging.StreamHandler()
    13 
    14 ch.setFormatter(form)
    15 # ch.setLevel(10)
    16 ch.setLevel(20)
    17 
    18 l1=logging.getLogger('root')
    19 # l1.setLevel(20)
    20 l1.setLevel(10)
    21 l1.addHandler(ch)
    22 
    23 l1.debug('l1 debug')
    24 
    25 重要,重要,重要!!!
    Logger<Handler的级别

    六、Logger的继承(了解)【父类,子类,孙子类】

     1 import logging
     2 
     3 formatter=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
     4                     datefmt='%Y-%m-%d %H:%M:%S %p',)
     5 
     6 ch=logging.StreamHandler()
     7 ch.setFormatter(formatter)
     8 
     9 
    10 logger1=logging.getLogger('root')
    11 logger2=logging.getLogger('root.child1')
    12 logger3=logging.getLogger('root.child1.child2')
    13 
    14 
    15 logger1.addHandler(ch)
    16 logger2.addHandler(ch)
    17 logger3.addHandler(ch)
    18 logger1.setLevel(10)
    19 logger2.setLevel(10)
    20 logger3.setLevel(10)
    21 
    22 logger1.debug('log1 debug')
    23 logger2.debug('log2 debug')
    24 logger3.debug('log3 debug')
    25 '''
    26 2018-04-18 10:22:05 AM - root - DEBUG -test:  log1 debug
    27 2018-04-18 10:22:05 AM - root.child1 - DEBUG -test:  log2 debug
    28 2018-04-18 10:22:05 AM - root.child1 - DEBUG -test:  log2 debug
    29 2018-04-18 10:22:05 AM- root.child1.child2 - DEBUG -test:  log3 debug
    30 2018-04-18 10:22:05 AM - root.child1.child2 - DEBUG -test:  log3 debug
    31 2018-04-18 10:22:05 AM - root.child1.child2 - DEBUG -test:  log3 debug
    32 '''
    View Code

    七、 应用(模板)

     1 """
     2 logging配置
     3 """
     4 
     5 import os
     6 import logging.config
     7 
     8 # 定义三种日志输出格式 开始
     9 
    10 standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' 
    11                   '[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字
    12 
    13 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
    14 
    15 id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
    16 
    17 # 定义日志输出格式 结束
    18 
    19 logfile_dir = os.path.dirname(os.path.abspath(__file__))  # log文件的目录
    20 
    21 logfile_name = 'all2.log'  # log文件名
    22 
    23 # 如果不存在定义的日志目录就创建一个
    24 if not os.path.isdir(logfile_dir):
    25     os.mkdir(logfile_dir)
    26 
    27 # log文件的全路径
    28 logfile_path = os.path.join(logfile_dir, logfile_name)
    29 
    30 # log配置字典
    31 LOGGING_DIC = {
    32     'version': 1,
    33     'disable_existing_loggers': False,
    34     'formatters': {
    35         'standard': {
    36             'format': standard_format
    37         },
    38         'simple': {
    39             'format': simple_format
    40         },
    41     },
    42     'filters': {},
    43     'handlers': {
    44         #打印到终端的日志
    45         'console': {
    46             'level': 'DEBUG',
    47             'class': 'logging.StreamHandler',  # 打印到屏幕
    48             'formatter': 'simple'
    49         },
    50         #打印到文件的日志,收集info及以上的日志
    51         'default': {
    52             'level': 'DEBUG',
    53             'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
    54             'formatter': 'standard',
    55             'filename': logfile_path,  # 日志文件
    56             'maxBytes': 1024*1024*5,  # 日志大小 5M
    57             'backupCount': 5,
    58             'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
    59         },
    60     },
    61     'loggers': {
    62         #logging.getLogger(__name__)拿到的logger配置
    63         '': {
    64             'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
    65             'level': 'DEBUG',
    66             'propagate': True,  # 向上(更高level的logger)传递
    67         },
    68     },
    69 }
    70 
    71 
    72 def load_my_logging_cfg():
    73     logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
    74     logger = logging.getLogger(__name__)  # 生成一个log实例
    75     logger.info('It works!')  # 记录该文件的运行状态
    76 
    77 if __name__ == '__main__':
    78     load_my_logging_cfg()
    79 
    80 logging配置文件
    日志模板
     1 """
     2 MyLogging Test
     3 """
     4 
     5 import time
     6 import logging
     7 import my_logging  # 导入自定义的logging配置
     8 
     9 logger = logging.getLogger(__name__)  # 生成logger实例
    10 
    11 
    12 def demo():
    13     logger.debug("start range... time:{}".format(time.time()))
    14     logger.info("中文测试开始。。。")
    15     for i in range(10):
    16         logger.debug("i:{}".format(i))
    17         time.sleep(0.2)
    18     else:
    19         logger.debug("over range... time:{}".format(time.time()))
    20     logger.info("中文测试结束。。。")
    21 
    22 if __name__ == "__main__":
    23     my_logging.load_my_logging_cfg()  # 在你程序文件的入口加载自定义logging配置
    24     demo()
    25 
    26 使用
    使用
     1 注意注意注意:
     2 
     3 
     4 #1、有了上述方式我们的好处是:所有与logging模块有关的配置都写到字典中就可以了,更加清晰,方便管理
     5 
     6 
     7 #2、我们需要解决的问题是:
     8     1、从字典加载配置:logging.config.dictConfig(settings.LOGGING_DIC)
     9 
    10     2、拿到logger对象来产生日志
    11     logger对象都是配置到字典的loggers 键对应的子字典中的
    12     按照我们对logging模块的理解,要想获取某个东西都是通过名字,也就是key来获取的
    13     于是我们要获取不同的logger对象就是
    14     logger=logging.getLogger('loggers子字典的key名')
    15 
    16     
    17     但问题是:如果我们想要不同logger名的logger对象都共用一段配置,那么肯定不能在loggers子字典中定义n个key   
    18  'loggers': {    
    19         'l1': {
    20             'handlers': ['default', 'console'],  #
    21             'level': 'DEBUG',
    22             'propagate': True,  # 向上(更高level的logger)传递
    23         },
    24         'l2: {
    25             'handlers': ['default', 'console' ], 
    26             'level': 'DEBUG',
    27             'propagate': False,  # 向上(更高level的logger)传递
    28         },
    29         'l3': {
    30             'handlers': ['default', 'console'],  #
    31             'level': 'DEBUG',
    32             'propagate': True,  # 向上(更高level的logger)传递
    33         },
    34 
    35 }
    36 
    37     
    38 #我们的解决方式是,定义一个空的key
    39     'loggers': {
    40         '': {
    41             'handlers': ['default', 'console'], 
    42             'level': 'DEBUG',
    43             'propagate': True, 
    44         },
    45 
    46 }
    47 
    48 这样我们再取logger对象时
    49 logging.getLogger(__name__),不同的文件__name__不同,这保证了打印日志时标识信息不同,但是拿着该名字去loggers里找key名时却发现找不到,于是默认使用key=''的配置
    50 
    51 !!!关于如何拿到logger对象的详细解释!!!
    重点解释loger
    另外一个django的配置,瞄一眼就可以,跟上面的一样
     1 #logging_config.py
     2 LOGGING = {
     3     'version': 1,
     4     'disable_existing_loggers': False,
     5     'formatters': {
     6         'standard': {
     7             'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]'
     8                       '[%(levelname)s][%(message)s]'
     9         },
    10         'simple': {
    11             'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
    12         },
    13         'collect': {
    14             'format': '%(message)s'
    15         }
    16     },
    17     'filters': {
    18         'require_debug_true': {
    19             '()': 'django.utils.log.RequireDebugTrue',
    20         },
    21     },
    22     'handlers': {
    23         #打印到终端的日志
    24         'console': {
    25             'level': 'DEBUG',
    26             'filters': ['require_debug_true'],
    27             'class': 'logging.StreamHandler',
    28             'formatter': 'simple'
    29         },
    30         #打印到文件的日志,收集info及以上的日志
    31         'default': {
    32             'level': 'INFO',
    33             'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,自动切
    34             'filename': os.path.join(BASE_LOG_DIR, "xxx_info.log"),  # 日志文件
    35             'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
    36             'backupCount': 3,
    37             'formatter': 'standard',
    38             'encoding': 'utf-8',
    39         },
    40         #打印到文件的日志:收集错误及以上的日志
    41         'error': {
    42             'level': 'ERROR',
    43             'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,自动切
    44             'filename': os.path.join(BASE_LOG_DIR, "xxx_err.log"),  # 日志文件
    45             'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
    46             'backupCount': 5,
    47             'formatter': 'standard',
    48             'encoding': 'utf-8',
    49         },
    50         #打印到文件的日志
    51         'collect': {
    52             'level': 'INFO',
    53             'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,自动切
    54             'filename': os.path.join(BASE_LOG_DIR, "xxx_collect.log"),
    55             'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
    56             'backupCount': 5,
    57             'formatter': 'collect',
    58             'encoding': "utf-8"
    59         }
    60     },
    61     'loggers': {
    62         #logging.getLogger(__name__)拿到的logger配置
    63         '': {
    64             'handlers': ['default', 'console', 'error'],
    65             'level': 'DEBUG',
    66             'propagate': True,
    67         },
    68         #logging.getLogger('collect')拿到的logger配置
    69         'collect': {
    70             'handlers': ['console', 'collect'],
    71             'level': 'INFO',
    72         }
    73     },
    74 }
    75 
    76 
    77 # -----------
    78 # 用法:拿到俩个logger
    79 
    80 logger = logging.getLogger(__name__) #线上正常的日志
    81 collect_logger = logging.getLogger("collect") #领导说,需要为领导们单独定制领导们看的日志
    模板信息(可以定义不同的级别和路径)
  • 相关阅读:
    DataPipeline合伙人&CPO陈雷:成为中国的世界级数据中间件厂商
    数字化转型提速,DataPipeline助力中石油产业大数据实时共享能力再提升
    IT168专访|DataPipeline 合伙人&CPO陈雷:我们致力于成为中国的世界级数据中间件厂商
    Odoo 新老版本关于action window动作绑定的两种写法
    关于 错误"ERROR:RELAXNGV:RELAXNG_ERR_EXTRACO NTENT: Element openerp has extra content: data"的处理
    Odoo 前期各版本的协议变化对比
    如何让odoo在执行如PG、Less编译等调用时出现的异常信息打印出来
    Odoo14 官方新版docker镜像跑起来网站页面异常 元素 '<xpath expr="//*[hasclass('o_footer_copyright_name')]">' 在母级视图中没有找到
    一种将历史地图坐标配准到GIS中的方法
    水利地理信息系统
  • 原文地址:https://www.cnblogs.com/zhaojingyu/p/8873130.html
Copyright © 2020-2023  润新知