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") #领导说,需要为领导们单独定制领导们看的日志
模板信息(可以定义不同的级别和路径)

 

posted @ 2018-04-18 11:30  随心朝阳  阅读(409)  评论(0编辑  收藏  举报