日誌級別level | 數值 |
---|---|
CRITICAL | 50 |
ERROR | 40 |
WARNING | 30 ,默認日誌級別 |
INFO | 20 |
DEBUG | 10 |
NOTSET | 0,表示不設置 |
日誌級別是指產生日誌的嚴重程度
設置一個級別後,嚴重程度低於次級別的日誌消息將會被忽略
數字越高,優先級別越高 python
#!/usr/bin/python3.6 #conding:utf-8 import threading import time import logging logging.basicConfig(level=logging.INFO) #設置日誌級別爲info def add(x,y): logging.warning(x+y) # 此處定義的日誌級別是warning,所以可以被打印出來,默認的日誌打印格式是 級別:用戶:信息 t=threading.Timer(1,add,args=(3,4)) # 此處表示6秒後出結果 t.start()
結果以下
安全
默認的日誌打印格式是級別:用戶:信息ide
屬性名 | 格式 | 描述 |
---|---|---|
日誌消息內容 | %(message)s | 當調用formatter.format() 時設置 |
asctime | %(asctime)s | 建立logrecord時的可讀時間,默認格式是Y-m-d H:M:S, (逗號後面的數字是毫秒部分的時間) |
函數名 | %(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 | 線程名字 |
d 格式化成數字,s格式化成字符串 函數
#!/usr/bin/python3.6 #conding:utf-8 import threading import time FORMAT="%(asctime)-15s\tThread Name: %(threadName)s\t%(message)s" # 此處定義日誌格式 import logging logging.basicConfig(level=logging.INFO,format=FORMAT) #設置日誌級別爲info,此處format爲引用日誌格式 def add(x,y): logging.warning(x+y) # 此處定義的日誌級別是warning,所以可以被打印出來 t=threading.Thread(target=add,args=(3,4),name='a1') t.start()
結果以下
線程
#!/usr/bin/python3.6 #conding:utf-8 import threading import time FORMAT="%(asctime)-15s\tThread Name: %(threadName)s\t%(message)s" # 此處定義日誌格式 import logging logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt='%y-%m-%d %H:%M:%S %z') #設置日誌級別爲info,此處format爲引用日誌格式,此處經過定義日誌格式來 # 肯定打印的日誌爲正常格式,其和%(asctime)互相做用 def add(x,y): logging.warning(x+y) # 此處定義的日誌級別是warning,所以可以被打印出來 t=threading.Thread(target=add,args=(3,4),name='a1') t.start()
結果以下
debug
不一樣打印風格日誌
#!/usr/bin/python3.6 #conding:utf-8 import threading import time FORMAT="%(asctime)-15s\tThread Name: %(threadName)s\t%(message)s" # 此處定義日誌格式 import logging logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt='%y-%m-%d %H:%M:%S %z') #設置日誌級別爲info,此處format爲引用日誌格式,此處經過定義日誌格式來 # 肯定打印的日誌爲正常格式,其和%(asctime)互相做用 def add(x,y): logging.warning("%d",x+y) # 此處定義的日誌級別是warning,所以可以被打印出來,此處是c風格處理日誌 logging.info("{} 值爲 {}".format(threading.enumerate(),x+y)) # 此處是format方式處理 t=threading.Thread(target=add,args=(3,4),name='a1') t.start()
打印結果以下 code
定義一個新的變量來進行存儲 orm
#!/usr/bin/python3.6 #conding:utf-8 import threading import time FORMAT="%(asctime)s \t threadName: %(threadName)s \t %(message)s \t %(myname1)s" # 此處定義日誌格式,此處定義變量名爲myname import logging logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt='%y-%m-%d %H:%M:%S %z') #設置日誌級別爲info,此處format爲引用日誌格式,此處經過定義日誌格式來 # 肯定打印的日誌爲正常格式,其和%(asctime)互相做用 d={"myname1":"zhangsan"} #此處定義變量值爲zhangsan,是字典格式 def add(x,y): logging.warning("%d",x+y,extra=d) # 此處定義的日誌級別是warning,所以可以被打印出來,此處是c風格處理日誌,經過此處引用extra 字典獲得結果 t=threading.Thread(target=add,args=(3,4),name='a1') t.start()
結果以下 對象
#!/usr/bin/python3.6 #conding:utf-8 import threading import time FORMAT="%(asctime)s \t threadName: %(threadName)s \t %(message)s \t %(myname1)s" # 此處定義日誌格式,此處定義變量名爲myname import logging logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt='%y-%m-%d %H:%M:%S %z',filename='/root/test.log') #設置日誌級別爲info,此處format爲引用日誌格式,此處經過定義日誌格式來 # 肯定打印的日誌爲正常格式,其和%(asctime)互相做用,此處指定打印的路徑,若不存在,則建立並追加,如此下面便不會再次打印 d={"myname1":"zhangsan"} #此處定義變量值爲zhangsan,是字典格式 def add(x,y): logging.warning("%d",x+y,extra=d) # 此處定義的日誌級別是warning,所以可以被打印出來,此處是c風格處理日誌,經過此處引用extra 字典獲得結果 t=threading.Thread(target=add,args=(3,4),name='a1') t.start()
結果以下
其至關於輸出重定向到文件
使用工廠方法返回一個logger實例。
logger.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的後代。
#!/usr/bin/python3.6 #conding:utf-8 import logging log=logging.getLogger() print (log.name) #打印當前實例的名稱,其默認名稱爲root print (type(log))# 打印當前實例的類型
結果以下
#!/usr/bin/python3.6 #conding:utf-8 import logging log=logging.getLogger('a') # 此處定義其名稱, print (log.name) #打印當前實例的名稱 print (log,type(log))# 打印當前實例的類型和實例狀況
結果以下
#!/usr/bin/python3.6 #conding:utf-8 import logging #!/usr/bin/poython3.6 #conding:utf-8 import logging root=logging.getLogger() print (root,id(root)) # 此處返回跟和跟地址 log=logging.getLogger('a') # 此處定義其名稱, print (log.name) #打印當前實例的名稱 print (log,type(log),log.parent,id(log),id(log.parent))# 打印當前實例的類型和實例狀況及其父類狀況,此處打印當前給狀況和父根狀況 # log1=logging.getLogger('a.b') print (log1.name) print (log1,type(log1),log1.parent,id(log1.parent))# 此處打印當前根父跟狀況
結果以下
上述代表,其a.b的父類是a,a的父類是root ,其直接存在父子級別
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.INFO,datefmt='%Y-%m-%d %H:%M:%S',format=FORMAT) root=logging.getLogger() root.warning('my root') log=logging.getLogger('a') # 此處定義其名稱, log.warning('my log') log1=logging.getLogger('a.b') log1.warning('my log1')
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.INFO,datefmt='%Y-%m-%d %H:%M:%S',format=FORMAT) root=logging.getLogger() print (root,id(root)) root.warning('my root') loga=logging.getLogger(__name__) # 此處使用模塊名稱進行定義名字 print (loga,id(loga),loga.name) loga.warning('my loga')# loga.name 也不能在此中打印出來 logb=logging.getLogger("{}.{}".format(__name__,'abcd')) # 此處使用模塊名稱下的具體方法定義名稱,經過format進行字符串的拼接 print (logb,id(logb),logb.name) logb.warning('my logb') # logb.name不能打印出來
結果以下
獲取和設置相關級別
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.INFO,datefmt='%Y-%m-%d %H:%M:%S',format=FORMAT) root=logging.getLogger() print (root,id(root)) print (root.getEffectiveLevel())#此處打印日誌級別 loga=logging.getLogger(__name__) # 此處使用模塊名稱進行定義名字 loga.warning('my loga')# loga.name 也不能在此中打印出來 print (loga.getEffectiveLevel())#此處打印日誌級別 logb=logging.getLogger("{}.{}".format(__name__,'abcd')) # 此處使用模塊名稱下的具體方法定義名稱,經過format進行字符串的拼接 logb.warning('my logb') # logb.name不能打印出來 logb.debug('my debug') # 此處的debug日誌將不能被打印出來 print (logb.getEffectiveLevel()) #此處打印日誌級別
結果以下
修改日誌級別並進行配置和獲取
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.INFO,datefmt='%Y-%m-%d %H:%M:%S',format=FORMAT) root=logging.getLogger() print (root,id(root)) print (root.getEffectiveLevel())#此處打印日誌級別 loga=logging.getLogger(__name__) # 此處使用模塊名稱進行定義名字 loga.info('my loga')# loga.name 也不能在此中打印出來 print (root.getEffectiveLevel())#此處打印日誌級別 print (loga.getEffectiveLevel())#此處打印日誌級別 loga.setLevel(28)# 此時日誌級別位於INFO 和 WARNING之間, print (loga.getEffectiveLevel()) # 獲取修改後的日誌級別 print ('+'*20,'logb') logb=logging.getLogger("{}.{}".format(__name__,'abcd')) # 此處使用模塊名稱下的具體方法定義名稱,經過format進行字符串的拼接 logb.info('my logb') # 此處由於自身沒有配置日誌級別,所以繼承了上面的日誌級別,所以,其不能打印 logb.setLevel(10) logb.info('my logb') # 此處由於自身設置了日誌級別,所以其能夠打印 logb.warning('my debug') print (logb.getEffectiveLevel()) #此處打印日誌級別
結果以下
全局能夠設定,但本身模塊能夠根據本身的狀況進行調整和修改
上述用於設置模塊和模塊對應函數或類的日誌級別,經過上述的定義能夠肯定打印日誌的級別和相關的配置狀況
向在模塊級別的進行配置和修改日誌的級別設置
想作個性化比較難
重要的主要是level和format 的狀況
handler 控制日誌信息的輸出目的地,能夠是控制檯,文件
能夠單獨設置level
能夠單獨設置格式
能夠設置過濾器
handler分爲
1 StreamHandler # 不指定使用sys.stderr
A FileHandler # 文件輸出
B _StderrHandler # 標準輸出
2 NullHandler # 什麼都不作Handler父類 ,FileHandle和_StderrHandler和NullHandler是子類,子類能夠繼承父類的相關屬性
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此處實例化出來一個對象 log1.setLevel(logging.WARNING) #設置此對象的相關屬性 h1=logging.StreamHandler() # 實例化一個標準輸出的handler h1.setLevel(logging.INFO) # 設置handler的級別 log1.addFilter(h1) # 將h1加入到log1 log1.info('info log1') # 打印INFO日誌。 log1.warning('warning log1') # 打印WARING ,此處只能打印WAENING
結果以下
此處代表,雖然handler設置了info級別,但其沒不能影響log1的設置,仍然不能打印info級別
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此處實例化出來一個對象 log1.setLevel(logging.INFO) #設置此對象的相關屬性 h1=logging.StreamHandler() # 實例化一個標準輸出的handler h1.setLevel(logging.ERROR) # 設置handler的級別 log1.addFilter(h1) # 將h1加入到log1 log1.warning('warning log1') # 打印WARING ,此處只能打印WAENING log1.info('info log1') log2=logging.getLogger('s.s1') #此處繼承了s1的屬性 print (log2.getEffectiveLevel()) log2.warning('wangring log2') #此處設置的warning 和handler中設置的ERROR不衝突,由於ERROR 不針對當前設置
結果以下
此處雖然handler設置了ERROR 級別,但info級別仍是可以打印出來,其不會影響當前級別的日誌,而繼承的日誌也沒受到handler的影響直接打印
日誌輸出到文件
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此處實例化出來一個對象 log1.setLevel(logging.INFO) #設置此對象的相關屬性 h1=logging.FileHandler('/root/test1.log') # 實例化一個文件輸出的handler h1.setLevel(logging.ERROR) # 設置handler的級別 log1.addHandler(h1) # 將h1加入到log1 log1.warning('warning log1') # 打印WARING ,此處只能打印WAENING log1.info('info log1') log1.error('error log1') #打印error級別
結果以下
文件中結果以下
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此處實例化出來一個對象 log1.setLevel(logging.WARNING) #設置此對象的相關屬性 h1=logging.FileHandler('/root/test1.log') # 實例化一個文件輸出的handler h1.setLevel(logging.INFO) # 設置handler的級別 log1.addHandler(h1) # 將h1加入到log1 log1.warning('warning log1') # 打印WARING ,此處只能打印WAENING log1.info('info log1')
結果以下
文件結果
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此處實例化出來一個對象 log1.setLevel(logging.WARNING) #設置此對象的相關屬性 h1=logging.FileHandler('/root/test1.log') # 實例化一個文件輸出的handler h1.setLevel(logging.INFO) # 設置handler的級別 log1.addHandler(h1) # 將h1加入到log1 log1.warning('warning log1') # 打印WARING ,此處只能打印WAENING log1.info('info log1') log2=logging.getLogger('s.s1') print (log2.getEffectiveLevel()) log2.info('log2 info')
文件結果
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此處實例化出來一個對象 log1.setLevel(logging.INFO) #設置此對象的相關屬性 h1=logging.FileHandler('/root/test1.log') # 實例化一個文件輸出的handler h1.setLevel(logging.INFO) # 設置handler的級別 log1.addHandler(h1) # 將h1加入到log1 log1.warning('warning log1') # 打印WARING ,此處只能打印WAENING log1.info('info log1') log2=logging.getLogger('s.s1') print (log2.getEffectiveLevel()) log2.info('log2 info')
結果
文件結果
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此處實例化出來一個對象 log1.setLevel(logging.INFO) #設置此對象的相關屬性 h1=logging.FileHandler('/root/test1.log') # 實例化一個文件輸出的handler h1.setLevel(logging.INFO) # 設置handler的級別 fmtr=logging.Formatter("%(asctime)s Threadinfo: %(threadName)s %(message)s %(thread)s") h1.setFormatter(fmtr) log1.addHandler(h1) # 將h1加入到log1 log1.warning('warning log1') # 打印WARING ,此處只能打印WAENING log1.info('info log1') log2=logging.getLogger('s.s1') print (log2.getEffectiveLevel()) log2.info('log2 info')
結果以下
文件結果以下
import logging root=logging.getLogger() root.setLevel(logging.ERROR) print ('root',root.handlers) #打印handler列表 h0=logging.StreamHandler() h0.setLevel(logging.WARNING) root.addHandler(h0) print ('root',root.handlers) # 打印列表 for h in root.handlers: print ("root handler = {} ,formatter= {}".format(h,h.formatter)) # 打印默認的formatter
結果以下
import logging root=logging.getLogger() root.setLevel(logging.ERROR) print ('root',root.handlers) #打印handler列表 h0=logging.StreamHandler() h0.setLevel(logging.WARNING) root.addHandler(h0) print ('root',root.handlers) # 打印列表 for h in root.handlers: print ("root handler = {} ,formatter= {}".format(h,h.formatter)) # 打印默認的formatter log1=logging.getLogger('s') log1.setLevel(logging.ERROR) h1=logging.FileHandler('/root/test2.log') log1.addHandler(h1) print ('log1',log1.handlers) log2=logging.getLogger('s.s1') log2.setLevel(logging.CRITICAL) h2=logging.FileHandler('/root/test2.log') h2.setLevel(logging.WARNING) print ('log2 formatter',h2.formatter) # handler 默認無Formatter f2=logging.Formatter("log2 %(name)s %(asctime)s %(message)s") h2.setFormatter(f2) print ('log2.formatter',h2.formatter) log2.addHandler(h2) print ('log2',log2.handlers)
結果爲
文件結果爲
1 每個logger實例的level如同入水口,讓水流進來,若是這個門檻過高,水流就不能進來,其相關低級別的信息必定不能被打印出來
2 若是level沒有設置,則使用父類logger的,若是父類沒有,則繼續尋找父類的,最終找到root,而root的默認設置是WARNING
3 消息傳遞流程
在某個logger上產生某種級別的消息,首先和logger的level檢查,若是消息level低於logger的EffectiveLevel有效級別,則丟棄消息,若是經過(大於等於)檢查後,消息交給全部的handler處理,每個handler須要和本身的level比較來決定是否處理,若是沒有一個handler,或者消息已經被處handler處理過了,則須要經過本logger的propagate屬性是不是True,True則會把這個消息繼續傳遞給父logger,父logger成爲新的logger。新的logger直接把消息交給新的logger的全部handler,handler都處理完了,若是paragate屬性是True,新的logger的父成爲新的logger,它的全部handler處理消息。
4 logger 實例初始化的paragate屬性爲True,及容許向父傳遞logger消息
5 logging.basicConfig
若是root沒有handler,就默認建立一個StreamHandler ,若是設置了filename,則就建立了一個FileHandler,若是設置了format參數,它就會生成一個formatter對象,並把這個formatter加入到剛纔建立的handler上,而後把這些handler加入到root.handlers列表上,level是設置給root logger的。若是root.handlers列表不是空,則logging.basicConfig的調用什麼都不作。
能夠爲handler增長過濾器,因此過濾器隻影響某一個handler,不會影響整個處理流程
import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.ERROR,format=FORMAT,datefmt="%y-%m-%d %H:%M%S %z") #從新格式化傳值,定義日誌輸出到文件 root=logging.getLogger() print (root,id(root)) loga=logging.getLogger('s') # 模塊和模塊下的某個函數或類 print (loga,id(loga),id(loga.parent)) loga.setLevel(logging.INFO) print (loga.getEffectiveLevel()) #默認對應的是常量20 hadr=logging.FileHandler('/root/loga.txt') # 定義,不指定則是標準錯誤輸出 hadr.setLevel(logging.INFO) fmtr=logging.Formatter("%(asctime)s %(thread)d %(threadName)s %(message)s") #此處是一個實例。此處能夠本身定義 hadr.setFormatter(fmtr) fltr=logging.Filter('s') # 此處設置過濾器爲s,則爲s,s.s1都可經過 hadr.addFilter(fltr) loga.addHandler(hadr) logb=logging.getLogger('s.s1') logb.getEffectiveLevel() logb.info('logb info')
結果以下
文件結果以下
import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.ERROR,format=FORMAT,datefmt="%y-%m-%d %H:%M%S %z") #從新格式化傳值,定義日誌輸出到文件 root=logging.getLogger() print (root,id(root)) loga=logging.getLogger('s') # 模塊和模塊下的某個函數或類 print (loga,id(loga),id(loga.parent)) loga.setLevel(logging.INFO) print (loga.getEffectiveLevel()) #默認對應的是常量20 hadr=logging.FileHandler('/root/loga.txt') # 定義,不指定則是標準錯誤輸出 hadr.setLevel(logging.INFO) fmtr=logging.Formatter("%(asctime)s %(thread)d %(threadName)s %(message)s") #此處是一個實例。此處能夠本身定義 hadr.setFormatter(fmtr) fltr=logging.Filter('s') # 此處設置過濾器爲s,則爲s,s.s1都可經過 hadr.addFilter(fltr) loga.addHandler(hadr) loga.info('loga info') logb=logging.getLogger('s.s1') logb.getEffectiveLevel() logb.info('logb info') logc=logging.getLogger('s.s1') logc.getEffectiveLevel() logc.info('logc info')
結果以下
文件以下
import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.ERROR,format=FORMAT,datefmt="%y-%m-%d %H:%M%S %z") #從新格式化傳值,定義日誌輸出到文件 root=logging.getLogger() print (root,id(root)) loga=logging.getLogger('s') # 模塊和模塊下的某個函數或類 print (loga,id(loga),id(loga.parent)) loga.setLevel(logging.INFO) print (loga.getEffectiveLevel()) #默認對應的是常量20 hadr=logging.FileHandler('/root/loga.txt') # 定義,不指定則是標準錯誤輸出 hadr.setLevel(logging.INFO) fmtr=logging.Formatter("%(asctime)s %(thread)d %(threadName)s %(message)s") #此處是一個實例。此處能夠本身定義 hadr.setFormatter(fmtr) fltr=logging.Filter('a') # 此處設置過濾器爲s,則爲s,s.s1都可經過 hadr.addFilter(fltr) loga.addHandler(hadr) loga.info('loga info') logb=logging.getLogger('s.s1') logb.getEffectiveLevel() logb.info('logb info') logc=logging.getLogger('s.s1') logc.getEffectiveLevel() logc.info('logc info')
文件以下
消息loga,它的名字是's',所以過濾器名字設置爲s,則s.s1,s.x和s都能經過,但其餘的則不能經過,不設置過濾器名字,全部消息都能經過,設置爲a,則和s,s.s1和s.s2無任何關係,所以其不能使用,實例對象只有一個,一旦同名,也是隻有一個,線程的不安全不會影響logging,只會影響print。