1. 程式人生 > >Python 日誌向控制檯和檔案輸出

Python 日誌向控制檯和檔案輸出

python中有日誌記錄模組logging,具體可能考官方API Logging

1.建立logger例項

logging模組是依靠呼叫Logger類的方法來實現的,Logger並不直接建立例項,而是通過呼叫logging.getLogger([name])建立logger例項,

每個例項都有自己的名字.

logger = logging.getLogger("mylogger")

如果沒有指定name,返回root logger.name和logger例項是一一對應的,無需把logger例項在各個模組中傳遞。只要知道name,就能得到同一個logger例項.

    2.日誌的級別

 logging模組通過事件的嚴重程度提供6種不同級別的日誌記錄,提示日誌的重要程度.

   Level     數值

              CRITICAL                      50

     ERROR                         40

              WARNING                     30

               INFO                             20

               DEBUG                         10

               NOTSET                        0

模組預設設定的級別是WARNING 即當且僅當等於或高於WARNING的事件會被記錄下來,

更改logger的預設level

logger.setLevel("INFO")  //此時小於INFO級別的日誌都不輸出, 大於等於INFO級別的日誌都輸出.

例如:

logger.debug("this is debug message")    # 不輸出  
logger.info("this is info message")        # 輸出 
logger.warning("this is warning message")  # 輸出 

3.建立一個handle物件,併為handler設定 level

通過handler物件可以將日誌記錄(log record)寫到不同的地方(destination),比如檔案,socket, 控制檯.

python提供了十幾種實用handler,比較常用有:

StreamHandler: 輸出到控制檯

FileHandler:   輸出到檔案

BaseRotatingHandler 可以按時間寫入到不同的日誌中。比如將日誌按天寫入不同的日期結尾的檔案檔案。
SocketHandler 用TCP網路連線寫LOG
DatagramHandler 用UDP網路連線寫LOG
SMTPHandler 把LOG寫成EMAIL郵寄出去

RotatingFileHandler  指定了單個log檔案的size的最大值和log檔案的數量的最大值,

如果檔案大於最大值,將分割為多個檔案,如果log檔案的數量多於最多個數,最老的log檔案將被刪除

fh = logging.FileHandler(logName) //logName是在某個路徑下的log檔名mylogger
fh.setLevel(logLevel)   //logLevel是傳入的日誌級別引數.

ch = logging.StreamHandler()

rh = logging.RotatingFileHandler(logName,maxBytes=  ,backupCount= )

4.formatter物件,定義handler 格式化輸出

formatter物件 可以指定日誌記錄的時間格式、程序號、檔名、函式名等資訊.

幾種常用格式:

%(asctime)s  //預設的日期格式精確到微秒,例如‘2016-03-16 8:20:34,896'

%(name)s   //logName mylogger

%(levelname)s  // logLevel 

%(message)s  //日誌資訊logger.debug("this is debug message")   this is debug message

%(filename)s //log.py

%(lineno)d  //原始檔中log日誌被呼叫的行號,logger.info("this is info message") 
log_format=logging.Formatter("%(asctime)s-%(name)s-%(levelname)s-%(message)s-[%(filename)s:%(lineno)d]")

為建立的handler物件新增輸出格式

fh.setFormatter(log_format)

5.為logger例項新增handler物件

每個logger可以擁有多個handler,通過addHandler()新增

logger.addHandler(fh)

6.呼叫logger例項對應級別的目志訊息輸出函式:

logger.debug("debug message")     
logger.info(" info message")      
logger.warning("warning message") 
logger.critical("critical message")

logger.error("error message")

程式碼如下:

#coding=utf-8
import loggingimport logging.handlers
logDir=r"D:\logs"
 def getLog():
   #建立一個logger例項
   logger = logging.getLogger("mylogger")
   llogger.setLevel("DEBUG") #設定級別為DEBUG,覆蓋掉預設級別WARNING
 #建立一個handler,用於寫入日誌檔案,handler可以把日誌內容寫到不同的地方
   logName = logDir + r"\\" + "test.log"
   fh = logging.FileHandler(logName)
   fh.setLevel("WARNING")
 #再建立一個handler,用於輸出控制檯
   ch = logging.StreamHandler()
   ch.setLevel("ERROR") 
#定義handler的格式輸出
   log_format=logging.Formatter("%(asctime)s-%(name)s-%(levelname)s-%(message)s-[%(filename)s:%(lineno)d]") 
   fh.setFormatter(log_format) #setFormatter() selects a Formatter object for this handler to use
   ch.setFormatter(log_format) 
 #為logger新增handler
   logger.addHandler(fh) 
   logger.addHandler(ch)
   
   logger.debug("debug message")
   logger.info("info message") 
   logger.warning("warning message")  
   logger.error("error message")   
   logger.critical("critical message")

 if __name__ = "__main__":
     getLog()

控制檯輸出: 
2016-03-17 15:02:44,065-mylogger-ERROR-error message-[log.py:26]
2016-03-17 15:02:44,065-mylogger-CRITICAL-critical message-[log.py:27]
test.log檔案輸出:
2016-03-17 15:02:44,065-mylogger-WARNING-warning message-[log.py:25]
2016-03-17 15:02:44,065-mylogger-ERROR-error message-[log.py:26]
2016-03-17 15:02:44,065-mylogger-CRITICAL-critical message-[log.py:27]

也可以封裝成一個類呼叫

#coding=utf-8
class Logger():
    def __init__(self, lognName, logLevel, logger):

        # 建立一個logger
        self.logger = logging.getLogger(logger)
        self.logger.setLevel(logging.DEBUG)

        # 建立一個handler,用於寫入日誌檔案
        fh = logging.FileHandler(logName)
        fh.setLevel(logLevel)

        # 再建立一個handler,用於輸出到控制檯
        ch = logging.StreamHandler()
        ch.setLevel(logLevel)

        # 定義handler的輸出格式    
        log_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s

        -[%(filename)s:%(lineno)d]')
        fh.setFormatter(log_format)
        ch.setFormatter(log_format)

        # 給logger新增handler
        self.logger.addHandler(fh)
        self.logger.addHandler(ch)
   
    def getlog(self):
        return self.logger


在另一個test.py檔案中呼叫
from log import Logger
logger = Logger(logname='log.txt', loglevel="INFO", logger="test.py").getlog()

另:logging.basicConfig函式

basicConfig()是為root logger 建立一個控制代碼(StreamHandler),當未給root logger 建立一個控制代碼時,logging的debug() info() warning() error()和critical()函式會自動呼叫系統預設的basicConfig()函式

#coding=utf-8
import logging
LOG_FILENAME="D:\test\log.txt"
logging.basicConfig(logName=LOG_FILENAME,level=logging.INFO,format = '%(asctime)s - %(levelname)s: %(message)s')
logging.info("info message")

LOG_FILENAME="D:\test\log2.txt"
<pre name="code" class="python">logging.basicConfig(logName=LOG_FILENAME,level=logging.WARNING,format = '%(asctime)s - %(levelname)s: %(message)s')
logging.error("error message")


注:error message不會記錄到D:\test\log2.txt,會全部記錄到log.txt檔案下

因為logger已經有一個控制代碼了,basicConfig不會創造一個新的控制代碼了,所以日誌資訊會輸出到第一個日誌檔案下