logging模块
1、 日志级别
1 CRITICAL = 50 #FATAL = CRITICAL 2 ERROR = 40 3 WARNING = 30 #WARN = WARNING 4 INFO = 20 5 DEBUG = 10 6 NOTSET = 0 #不设置
2、默认级别为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 '''
3、为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 2017-07-28 20:32:17 PM - root - DEBUG -test: 调试debug
51 2017-07-28 20:32:17 PM - root - INFO -test: 消息info
52 2017-07-28 20:32:17 PM - root - WARNING -test: 警告warn
53 2017-07-28 20:32:17 PM - root - ERROR -test: 错误error
54 2017-07-28 20:32:17 PM - root - CRITICAL -test: 严重critical
55
56 part2: 可以为logging模块指定模块级的配置,即所有logger的配置
4、logging模块的Formatter,Handler,Logger,Filter对象
1 #logger:产生日志的对象 2 3 #Filter:过滤日志的对象 4 5 #Handler:接收日志然后控制打印到不同的地方,FileHandler用来打印到文件中,StreamHandler用来打印到终端 6 7 #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')
5、Logger与Handler的级别
logger是第一级过滤,然后才能到handler,我们可以给logger和handler同时设置level,但是需要注意的是

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 重要,重要,重要!!!
6、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 2017-07-28 22:22:05 PM - root - DEBUG -test: log1 debug
27 2017-07-28 22:22:05 PM - root.child1 - DEBUG -test: log2 debug
28 2017-07-28 22:22:05 PM - root.child1 - DEBUG -test: log2 debug
29 2017-07-28 22:22:05 PM - root.child1.child2 - DEBUG -test: log3 debug
30 2017-07-28 22:22:05 PM - root.child1.child2 - DEBUG -test: log3 debug
31 2017-07-28 22:22:05 PM - root.child1.child2 - DEBUG -test: log3 debug
32 '''
7、 应用

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对象的详细解释!!!
另外一个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") #领导说,需要为领导们单独定制领导们看的日志
来源:https://www.cnblogs.com/ershier/p/9433476.html
