logging 模塊的簡單使用:

配置輸出日誌到文件


導入模塊
import logging,os
FILE = os.getcwd()
設置文件路徑,默認是追加到文件中,不過可以設置filemode="w",爲重寫進去。
logging.basicConfig(filename=os.path.join(FILE,"dosubprocess.log"),filemode="w",
                    format="%(levelname)s:%(message)s",level=logging.INFO)
                    
                    
                    

可以在外面設置級別


import logging
logging.basicConfig(level="laowang")
#必須調用getLOgger獲得一個loggging對象後,纔可以爲他設置級別。
log=logging.getLogger(__name__)
#logging的屬性,propagate,意思是是否消息是否層層上傳。
print(log.propagate)
#設置logging對象的級別
log.setLevel(logging.WARN)

logging創建流handler,將信息顯示到控制檯,

import logging,os
logging.basicConfig(filename=os.path.join(os.getcwd(),"my_property.log"),
                    format="%(levelname)-10s %(asctime)-20s %(message)s",
                    datefmt="%m/%d/%Y %I:%M:%S",
                    level=logging.DEBUG,
                    filemode="w")

console=logging.StreamHandler()
console.setLevel(logging.INFO)
formatter=logging.Formatter("%(levelname)-10s %(asctime)-20s %(message)s")
console.setFormatter(formatter)
logging.getLogger("").addHandler(console)

'''
快速入門
基礎知識
日誌的作用是跟蹤,django項目中不可缺少。

派出:

控制檯輸出:print()

報告事件,發生在一個程序的正常運行:logging.info() 或 logging.debug()

發出警告關於一個特定的運行時事件:warnings.warn() 或 logging.warning()

報告一個錯誤對於一個特定的運行時事件:異常處理

報告一個錯誤當沒有引發一個異常:logging.error()、logging.exception() 或 logging.critical()

DEBUG:詳細的信息,通常只出現在診斷問題上

INFO:確認一切按預期運行

WARNING:一個跡象表明,一些意想不到的事情發生了,或表明一些問題在不久的將來(例如。磁盤空間低”)。這個軟件還能按預期工作

ERROR:個更嚴重的問題,軟件沒能執行一些功能

CRITICAL:一個嚴重的錯誤,這表明程序本身可能無法繼續運行

日誌一共分成5個等級,從低到高分別是:DEBUG INFO WARNING ERROR CRITICAL。這5個等級,也分別對應5種打日誌的方法: debug 、info 、warning 、error 、critical。

默認的是WARNING,當在WARNING或之上時才被跟蹤。
有兩種方式記錄跟蹤,一種輸出控制檯,另一種是記錄到文件中,如日誌文件。

日誌一共分成5個等級,從低到高分別是:DEBUG INFO WARNING ERROR CRITICAL。這5個等級,也分別對應5種打日誌的方法: debug 、info 、warning 、error 、critical。
默認的是WARNING,當在WARNING或之上時才被跟蹤。
有兩種方式記錄跟蹤,一種輸出控制檯,另一種是記錄到文件中,如日誌文件

'''

'''
簡單日誌操作
寫入一個文件裏面:
'''
#logging to file
# import os
# import logging
#
# # with open("log.txt","w",encoding="utf-8") as f:
# #     f.write("")
#
# FILE =os.getcwd()
# logging.basicConfig(filename=os.path.join(FILE,"log.txt"),level=logging.DEBUG)
# logging.debug("寫進去")
# logging.info("滾進去")
# logging.warning("也滾進去")
'''
來學習一些日誌組件以及一些高級部分。
日誌組件包括:loggers、handlers、filters、formatters。

Logger 對象扮演了三重角色。
首先,它暴露給應用幾個方法以便應用可以在運行時寫log;
其次,Logger對象按照log信息的嚴重程度或者
根據filter對象來決定如何處理log信息(默認的過濾功能);
最後,logger還負責把log信息傳送給相關的loghandlers。

Handler對象負責分配合適的log信息(基於log信息的嚴重 程度)到handler指定的目的地。
Logger對象可以用addHandler()方法添加零個或多個handler對象到它自身。
一個常見的場景是,一個應用可能希望把所有的log信息都發送到一個log文件中去,
所有的error級別以上的log信息都發送到stdout,
所有critical 的log信息通過email發送。
這個場景裏要求三個不同handler處理,每個handler負責把特定的log信息發送到特定的地方。

filter:細緻化,選擇哪些日誌輸出

format:設置顯示格式

'''
'''
ogging.basicConfig ( [ * * kwargs ] )
該語句是日誌模塊配置基本信息。kwargs 支持如下幾個關鍵字參數:

filename :日誌文件的保存路徑。如果配置了些參數,將自動創建一個FileHandler作爲Handler;

filemode :日誌文件的打開模式。 默認值爲’a’,表示日誌消息以追加的形式添加到日誌文件中。如果設爲’w’, 那麼每次程序啓動的時候都會創建一個新的日誌文件;

format :設置日誌輸出格式;

datefmt :定義日期格式;

level :設置日誌的級別.對低於該級別的日誌消息將被忽略;

stream :設置特定的流用於初始化StreamHandler。

'''
'''
logging.getLogger ( [ name ] )
創建Logger對象。日誌記錄的工作主要由Logger對象來完成。

在調用getLogger時要提供Logger的名稱(注:多次使用相同名稱 來調用getLogger,
返回的是同一個對象的引用。),Logger實例之間有層次關係,這些關係通過Logger名稱來體現,如
'''
# import logging

'''命名'''
# log2=logging.getLogger("BeginMan") #生成一個日誌對象
# print(log2)#<logging.Logger object at 0x00000000026D1710>
'''無名'''
# log3=logging.getLogger()
# print(log3)

'''最好的方式'''
# log = logging.getLogger(__name__)#_name__ is the module’s name in the Python package namespace.
# print(log)
# print(__name__)
'''
Logger對象,
有如下屬性和方法:
Logger.propagate

具體參考:http://docs.python.org/2.7/library/logging.html Logger.setLevel(lvl) 
——————– 設置日誌的級別。對於低於該級別的日誌消息將被忽略。

'''
# import logging
# import os
# logging.basicConfig(format="%(levelname)s,%(message)s",filename=os.path.join(os.getcwd(),"log.txt"),level=logging.DEBUG)
# log=logging.getLogger("root.set") #Logger 對象
# print(log.propagate)
#
# log.setLevel(logging.WARN) #日誌記錄級別爲WARNNING
# log.info("msg")
# log.debug("msg")
# log.warning("msg")
# log.error("msg")
#
'''
Handler對象、Formatter對象、Filter對象、Filter對象

'''

# import logging
# import os
# '''logger'''
# l=logging.Logger("root")  #創建logger對象
# log=logging.getLogger("root")  #通過logging.getlogger創建對象
#
# print(l)
# print(log)
#
# '''Handler'''
# handler=logging.Handler() #創建Handler對象
# handler.__init__(logging.DEBUG)  #通過設置levell勞初始刷handler實例
# handler.createLock()#初始化一個縣城索,可以用來序列化,訪問底層i/ogongneng,這可鞥不是縣城安全的
# handler.acquire() #獲取線程鎖,通過handler.createLock()
# handler.release() #釋放獲得的縣城索
# handler.setLevel(logging.DEBUG) #設置臨界值,如果logging信息級別小於他的責被忽視
# handler.setFormatter("%(levelname)s,%(message)s") #設置格式
# handler.addFilter(filter)#
'''
3.將日誌同時輸出到文件和屏幕
'''
# import logging
# logging.basicConfig(level=logging.DEBUG,
#                     format="%(asctime)s %(filename)s [line:%(lineno)d %(levelname)s %(message)s",
#                     datefmt="%a %d %b %Y  %H:%M:%S",
#                     filename="myapp.log",
#                     filemode="w")
# 定義一個StreamHandler,將INFO級別或更高的日誌信息打印到標準錯誤,
# 並將其添加到當前的日誌處理對象
# console=logging.StreamHandler()
# console.setLevel(logging.INFO)
# formatter=logging.Formatter("%(name)-12s:%(levelname)-8s %(message)s")
# console.setFormatter(formatter)
# logging.getLogger("").addHandler(console)
#
# logging.debug("This is debug message")
# logging.info("This is info message ")
# logging.warning("Thsi is warning message")


# level: 設置日誌級別,默認爲logging.WARNING
# stream: 指定將日誌的輸出流,
# 可以指定輸出到sys.stderr,sys.stdout或者文件,默認輸出到sys.stderr,
# 當stream和filename同時指定時,stream被忽略

'''
. 每一個Logger實例的level如同入口,讓水流進來,如果這個門檻太高,信息就進不來。例如log2.info('log3 info'),如果log2定義的級別高於info級別,就不會又信息通過log2

2. 如果level沒有設置,就用父logger的,如果父logger的level也沒有設置,繼續找父的父的,最終找到root上,如果root設置了就用它的,如果root沒有設置,root的默認值是WARNING

3.消息傳遞流程:

在某個logger上產生某種級別的信息,首先和logger的level檢查,如果消息level低於logger的EffectiveLevl有效級別,消息丟棄,不會再向父logger傳遞該消息。如果通過(大於等於)檢查後,則把消息交給logger所有的handler處理,每一個handler需要和自己level比較來決定是否處理。

 

如果沒有一個handler,或者消息已經被handler處理過了,則需要通過本logger的propagate屬性是否爲True,Ture則把這個消息會繼續發給父Logger,當前Logger的父Logger稱爲當前Logger,新的Logger的所有Handler繼續處理消息。

4. logger實例初始的propagate屬性爲True,即允許想父logger傳遞消息

5. logger.basicConfig

如果root沒有handler,就默認創建一個StreamHandler,如果設置了filename,就創建一個FileHandler。如果設置了format參數,就會用它生成一個formatter對象,並把這個formatter加入到剛纔創建的handler上,然後把這些handler加入到root.handlers列表上。level 是設置給root.logger的。

如果root.handlers列表不爲空,logging.basicConfig的調用什麼都不做。



標準庫裏面的logging模塊,在前面學習線程安全時曾用來解決print被打斷的問題,這裏會介紹logging模塊的功能。

logging模塊是線程安全的,不需要客戶做任何特殊的工作。它通過使用線程鎖實現了這一點; 有一個鎖來序列化訪問模塊的共享數據,
每個處理程序還創建一個鎖來序列化訪問其底層 I/O。


使用工廠方法返回一個Logger實例。

logging.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的後代。

'''

# import logging
# DATEFMT="[%Y-%m-%d %H:%M:%s]"
# FORMAT="%(asctime)s %(thread)d %(message)s"
# logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt=DATEFMT,filename="log.txt")
#
# root=logging.getLogger()
# print(root.name,type(root),root.parent,id(root))
#
# logger=logging.getLogger(__name__)
# print(logger.name,type(logger),id(logger),id(logger.parent))
#
# logger1=logging.getLogger(__name__+".ok")
# print(logger1.name,type(logger1),id(logger1),id((logger1.parent)))
#
# print(logger1.parent,id(logger.parent))
'''
子child的級別設置,不影響父parent的級別:
'''
# import logging
#
# FORMAT="%(asctime)s %(thread)d %(message)s"
# logging.basicConfig(level=logging.WARNING,format=FORMAT,datefmt="[%Y-%m-%d %H:%M:%S]")
#
# root=logging.getLogger()
# print(1,root,id(root))
# root.info("my root")
#
# loga=logging.getLogger(__name__)
# print(2,id(loga),id(loga.parent))
# print(3,loga.getEffectiveLevel())
#
# loga.warning("before")
# loga.setLevel(28)
# print(4,loga.getEffectiveLevel)
# loga.info("after")
# loga.warning("after")
'''
Handler

  StreamHandler #不指定使用sys.strerr

    FileHandler #文件

    _StderrHandler #標準輸出

  NullHandler #什麼都不做

logger實例,如果設置了level,就用它和信息的級別比較,否則,繼承最近的祖先的level。

'''

# import logging
# FORMAT ="%(asctime)s %(thread)d %(message)s"
# logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt="[%Y-%m-%d %H:%M:%S]")
#
# root=logging.getLogger()
# print("root",root.getEffectiveLevel())
#
# log1=logging.getLogger("s")
# log1.setLevel(logging.ERROR)
# print("log1:",log1.getEffectiveLevel())
# log1.error("log1 error")
#
# log2=logging.getLogger("s.s1")
# log2.setLevel(logging.WARNING)
# print("log2",log2.getEffectiveLevel())
# log2.warning("log2 warning")
#
#

'''
Handler:

Handler控制日誌信息的輸出目的地,可以是控制檯、文件。

可以單獨設置level

可以單獨設置格式

可以設置過濾器

 

Handler

  StreamHandler #不指定使用sys.strerr

    FileHandler #文件

    _StderrHandler #標準輸出

  NullHandler #什麼都不做

'''
# import logging
#
# FORMAT ="%(asctime)s %(thread)d %(message)s"
# logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt="[%Y-%m-%d %H:%M:%S]")
#
# root=logging.getLogger()
# print("root:",root.getEffectiveLevel())
#
# log1=logging.getLogger("s")
# log1.setLevel(logging.ERROR)
# print("log1:",log1.getEffectiveLevel())
# log1.error("log1.error")
#
# log2=logging.getLogger("s.s1")
# log2.setLevel(logging.WARNING)
# print("log2:",log2.getEffectiveLevel())
# log2.warning("log2.warning")

'''
loggerLevel --> FilterConditions --> HandlerLevel --> 
父LoggerFilter --> 父LoggerHandler --> RootHandler --> 標準輸出或記錄到日誌:


'''

import logging,datetime

FORMAT="%(asctime)s %(thread)s %(message)s"
logging.basicConfig(level=logging.WARNING,format=FORMAT,datefmt="[%Y-%m-%d %H:%M:%S]")

"--------------root----------------------"
root=logging.getLogger()
print(1,root.getEffectiveLevel())
"---------------------log1---------------------"
log1=logging.getLogger("s")
log1.setLevel(logging.ERROR)
print(2,log1.getEffectiveLevel())

h1=logging.FileHandler("h1.log")
h1.setLevel(logging.INFO)
log1.addHandler(h1)

"----------------log2-----------"
log2=logging.getLogger("s.s2")
log2.setLevel(logging.WARNING)
print(3,log2.getEffectiveLevel())

h2=logging.FileHandler("h2.log")
h2.setLevel(logging.WARNING)
f2=logging.Filter("s.s3")
h2.addFilter(f2)
log2.addHandler(h2)

log2.warning("4,log2 warning---{}".format(datetime.datetime.now()))
如果要實現多個模塊用一個定義好的logging模式,可以定義一個模板,
然後各個模塊在導入的時候,調用一下,就好啦。
文件一  log1
import logging
from string import Template

def lo():
    logging.info("log1--------------")
    logging.warning("name:%s msg:%s","BeginMan","Hi")
    logging.warning("name:%s msg:%s"%("BeginMan","Hi"))
    logging.warning("name:{0} mag:{1}".format("b而過inMan","HI"))
    msg=Template("name:$who msg:$what")
    logging.warning(msg.substitute(who="BeginMan",what="Hi"))
    
文件log2    
import logging
import os
FIFE  =os.getcwd()
import log1


def main():
    logging.basicConfig(filename=os.path.join(FIFE,"log1.txt"),level=logging.INFO)
    logging.info("start-------------")
    log1.lo()
    logging.info("end---------")
if __name__=="__main__":
    main()

發佈了42 篇原創文章 · 獲贊 5 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章