logging日志模块
一:日志级别
只有大于等于当前日志等级的操作才会被记录。
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
如何查找级别:

二:默认级别为warning,默认打印到终端
案例:
import logging
结果: 把level=10删掉:
|
三:为logging模块指定全局配置,针对所有logger有效,控制打印到文件中
|
可在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参数会被忽略
|
|
#格式
%(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模块的Formatter,Handler,Logger,Filter对象
logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。
基本用法:
import logging import sys # 获取logger实例,如果参数为空则返回root logger logger = logging.getLogger("AppName") # 指定logger输出格式 formatter = logging.Formatter('%(asctime)s %(levelname)-8s: %(message)s') # 文件日志 file_handler = logging.FileHandler("test.log") file_handler.setFormatter(formatter) # 可以通过setFormatter指定输出格式 # 控制台日志 console_handler = logging.StreamHandler(sys.stdout) console_handler.formatter = formatter # 也可以直接给formatter赋值 # 为logger添加的日志处理器 logger.addHandler(file_handler) logger.addHandler(console_handler) # 指定日志的最低输出级别,默认为WARN级别 logger.setLevel(logging.INFO) # 输出不同级别的log logger.debug('this is debug info') logger.info('this is information') logger.warn('this is warning message') logger.error('this is error message') logger.fatal('this is fatal message, it is same as logger.critical') logger.critical('this is critical message') # 2016-10-08 21:59:19,493 INFO : this is information # 2016-10-08 21:59:19,493 WARNING : this is warning message # 2016-10-08 21:59:19,493 ERROR : this is error message # 2016-10-08 21:59:19,493 CRITICAL: this is fatal message, it is same as logger.critical # 2016-10-08 21:59:19,493 CRITICAL: this is critical message # 移除一些日志处理器 logger.removeHandler(file_handler) |
|
#logger:产生日志的对象
#Filter:过滤日志的对象
#Handler:接收日志然后控制打印到不同的地方,FileHandler用来打印到文件中,StreamHandler用来打印到终端
#Formatter对象:可以定制不同的日志格式对象,然后绑定给不同的Handler对象使用,以此来控制不同的Handler的日志格式
|
1 import logging 2 3 4 5 #1、logger对象:负责产生日志,然后交给Filter过滤,然后交给不同的Handler输出 6 7 logger=logging.getLogger(__file__) 8 9 10 11 #2、Filter对象:不常用,略 12 13 14 15 #3、Handler对象:接收logger传来的日志,然后控制输出 16 17 h1=logging.FileHandler('t1.log') #打印到文件 18 19 h2=logging.FileHandler('t2.log') #打印到文件 20 21 h3=logging.StreamHandler() #打印到终端 22 23 24 25 #4、Formatter对象:日志格式 26 27 formmater1=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', 28 29 datefmt='%Y-%m-%d %H:%M:%S %p',) 30 31 32 33 formmater2=logging.Formatter('%(asctime)s : %(message)s', 34 35 datefmt='%Y-%m-%d %H:%M:%S %p',) 36 37 38 39 formmater3=logging.Formatter('%(name)s %(message)s',) 40 41 42 43 44 45 #5、为Handler对象绑定格式 46 47 h1.setFormatter(formmater1) 48 49 h2.setFormatter(formmater2) 50 51 h3.setFormatter(formmater3) 52 53 54 55 #6、将Handler添加给logger并设置日志级别 56 57 logger.addHandler(h1) 58 59 logger.addHandler(h2) 60 61 logger.addHandler(h3) 62 63 logger.setLevel(10) 64 65 66 67 #7、测试 68 69 logger.debug('debug') 70 71 logger.info('info') 72 73 logger.warning('warning') 74 75 logger.error('error') 76 77 logger.critical('critical') |
五:应用案例:
def func(): try: a =a +1 except Exception as e: print(e) #local variable 'a' referenced before assignment 注意e是对象,打印对象之所以能打印出字符串是因为执行__str__ logging.error(str(e)) func()
结果:
缺点:这样的日志信息我们无法具体获得报错信息。 |
六:应用案例升级
import logging import traceback logging.basicConfig(filename='xxx.log', format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S ', ) def func(): try: a =a +1 except Exception as e: #e是对象,我们通常利用e获得封装的数据 #获取当前错误的堆栈信息 msg = traceback.format_exc() logging.error(msg) func()
|
七:坑
1 import logging 2 3 4 5 logging.basicConfig(filename='x1.log', 6 format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', 7 datefmt='%Y-%m-%d %H:%M:%S ', 8 level=10 9 ) 10 logging.basicConfig(filename='x2.log', 11 format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', 12 datefmt='%Y-%m-%d %H:%M:%S ', 13 level=10 14 ) 15 16 logging.debug('debug') 17 logging.debug('debug')
这种情况,我们希望两个文件都写或者分别记录到不同日志里。但我们可以看结果。 x2.log这个文件没有形成,都放在x1.log文件里了。
造成这种情况的原因: logging.basicConfig会在内存中配置,但是如果在来logging.basicConfig会查看内存,有的话就不做了。这样只能第一次生效。归根结底造成这种问题是日志中使用了重复的handler那么非要写到两个日志文件里怎么办呢?就形成不同的handler对象就可以,如下:
1 import logging 2 3 4 # 创建一个操作日志的对象logger(依赖FileHandler) 5 file_handler = logging.FileHandler('l1.log', 'a', encoding='utf-8') 6 file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s")) 7 8 logger1 = logging.Logger('s1', level=logging.ERROR) 9 logger1.addHandler(file_handler) 10 11 12 logger1.error('123123123') 13 14 15 # 在创建一个操作日志的对象logger(依赖FileHandler) 16 file_handler2 = logging.FileHandler('l2.log', 'a', encoding='utf-8') 17 file_handler2.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s")) 18 19 logger2 = logging.Logger('s2', level=logging.ERROR) 20 logger2.addHandler(file_handler2) 21 22 logger2.error('666')
|





浙公网安备 33010602011771号