日志
如果你曾經在代碼中加入 print() 語句,在程序運行時輸出某些變量的值,你就使用了記日志的方式來調試代碼。記日志是一種很好的方式,可以理解程序中發生的事,以及事情發生的順序。 Python 的 logging 模塊使得你很容易創建自定義的消息記錄。這些日志消息將描述程序執行何時到達日志函數調用,并列出你指定的任何變量當時的值。另一方面,缺失日志信息表明有一部分代碼被跳過,從未執行。
使用日志模塊
要啟用
logging 模塊
,在程序運行時將日志信息顯示在屏幕上,請將下面的代碼復制到程序頂部(但在 Python 的#!行之下):
import
logging
logging
.
basicConfig
(
level
=
logging
.
DEBUG
,
format
=
' %(asctime)s - %(levelname)s- %(message)s'
# 日志打印格式
)
基本上,當 Python 記錄一個事件的日志時,它會創建一個 LogRecord 對象,保存關于該事件的信息。 logging 模塊的函數讓你指定想看到的這個 LogRecord 對象的細節,以及希望的細節展示方式。
假如你編寫了一個函數,計算一個數的階乘。在數學上, 4 的階乘是1 × 2 × 3 × 4,即 24。 7 的階乘是 1 × 2 × 3 × 4 × 5 × 6 × 7,即 5040。打開一個新的文件編輯器窗口,輸入以下代碼。其中有一個缺陷,但你也會輸入一些日志信息,幫助你弄清楚哪里出了問題。
import
logging
logging
.
basicConfig
(
level
=
logging
.
DEBUG
,
format
=
' %(asctime)s - %(levelname)s- %(message)s'
)
logging
.
debug
(
'Start of program'
)
def
factorial
(
n
)
:
logging
.
debug
(
'Start of factorial(%s%%)'
%
(
n
)
)
total
=
1
for
i
in
range
(
n
+
1
)
:
total
*=
i
logging
.
debug
(
'i is '
+
str
(
i
)
+
', total is '
+
str
(
total
)
)
logging
.
debug
(
'End of factorial(%s%%)'
%
(
n
)
)
return
total
print
(
factorial
(
5
)
)
logging
.
debug
(
'End of program'
)
輸出:
0
2019-06-17 14:17:35,350 - DEBUG- Start of program
2019-06-17 14:17:35,350 - DEBUG- Start of factorial(5%)
2019-06-17 14:17:35,350 - DEBUG- i is 0, total is 0
2019-06-17 14:17:35,350 - DEBUG- i is 1, total is 0
2019-06-17 14:17:35,350 - DEBUG- i is 2, total is 0
2019-06-17 14:17:35,350 - DEBUG- i is 3, total is 0
2019-06-17 14:17:35,350 - DEBUG- i is 4, total is 0
2019-06-17 14:17:35,350 - DEBUG- i is 5, total is 0
2019-06-17 14:17:35,350 - DEBUG- End of factorial(5%)
2019-06-17 14:17:35,350 - DEBUG- End of program
打印日志信息時,使用 logging.debug() 函數。這個 debug() 函數將調用 basicConfig(),打印一行信息。這行信息的格式是我們在 basicConfig()函數中指定的,并且包括我們傳遞給 debug() 的消息。
factorial() 函數返回 0 作為 5 的階乘,這是不對的。 for 循環應該用從 1 到 5的數,乘以 total 的值。但 logging.debug() 顯示的日志信息表明, i 變量從 0 開始,而不是 1。因為 0 乘任何數都是 0,所以接下來的迭代中, total 的值都是錯的。日志消息提供了可以追蹤的痕跡,幫助你弄清楚何時事情開始不對。將代碼行
for i in range(n + 1)
:改為
for i in range(1, n + 1):
,再次運行程序。
輸出看起來像這樣:
輸出:
120
2019-06-17 14:22:30,612 - DEBUG- Start of program
2019-06-17 14:22:30,612 - DEBUG- Start of factorial(5%)
2019-06-17 14:22:30,612 - DEBUG- i is 1, total is 1
2019-06-17 14:22:30,612 - DEBUG- i is 2, total is 2
2019-06-17 14:22:30,612 - DEBUG- i is 3, total is 6
2019-06-17 14:22:30,612 - DEBUG- i is 4, total is 24
2019-06-17 14:22:30,612 - DEBUG- i is 5, total is 120
2019-06-17 14:22:30,612 - DEBUG- End of factorial(5%)
2019-06-17 14:22:30,612 - DEBUG- End of program
日志級別
“日志級別”提供了一種方式,按重要性對日志消息進行分類。 5 個日志級別如表所示,從最不重要到最重要。利用不同的日志函數,消息可以按某個級別記入日志。
日志的級別
import
logging
logging
.
debug
(
'debug message'
)
logging
.
info
(
'info message'
)
logging
.
warning
(
'warning message'
)
logging
.
error
(
'error message'
)
logging
.
critical
(
'critical message'
)
靈活配置日志級別,日志格式,輸出位置
除了將日志消息顯示在屏幕上,還可以將它們寫入文本文件。
logging.basicConfig() 函數
接受 filename 關鍵字參數,
import
logging
logging
.
basicConfig
(
filename
=
'myProgramLog.txt'
,
level
=
logging
.
DEBUG
,
format
=
'%(asctime)s - %(levelname)s - %(message)s'
)
日志信息將被保存到 myProgramLog.txt 文件中。雖然日志消息很有用,但它們可能塞滿屏幕,讓你很難讀到程序的輸出。將日志信息寫入到文件,讓屏幕保持干凈,又能保存信息,這樣在運行程序后,可以閱讀這些信息。可以用任何文件編輯器打開這個文本文件,諸如 Notepad 或 TextEdit。
日志文本默認的是
追加方式進行寫入的
,可以更改寫入的方式
filemode=‘w
logging
.
basicConfig
(
filename
=
'myProgramLog.txt'
,
level
=
logging
.
DEBUG
,
format
=
'%(asctime)s - %(levelname)s - %(message)s'
,
filemode
=
'w'
)
logging.basicConfig()函數
中可通過具體參數來更改logging模塊默認行為,可用參數有
-
filename
:用指定的文件名創建FiledHandler,這樣日志會被存儲在指定的文件中。 -
filemode
:文件打開方式,在指定了filename時使用這個參數,默認值為“a”還可指定為“w”。 -
format
:指定handler使用的日志顯示格式。 -
datefmt
:指定日期時間格式。 -
level
:設置rootlogger的日志級別 - stream:用指定的stream創建StreamHandler。可以指定輸出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,‘w’)),默認為sys.stderr。若同時列出了filename和stream兩個參數,則stream參數會被忽略。
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
=
'test.log'
,
filemode
=
'w'
)
logging
.
debug
(
'debug message'
)
logging
.
info
(
'info message'
)
logging
.
warning
(
'warning message'
)
logging
.
error
(
'error message'
)
logging
.
critical
(
'critical message'
)
輸出:test.log
format參數中可能用到的格式化串:
- %(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用戶輸出的消息
logger對象
上述幾個例子中我們了解到了logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical()(分別用以記錄不同級別的日志信息),logging.basicConfig()(用默認日志格式(Formatter)為日志系統建立一個默認的流處理器(StreamHandler),設置基礎配置(如日志級別等)并加到root logger(根Logger)中)這幾個logging模塊級別的函數,另外還有一個模塊級別的函數是logging.getLogger([name])(返回一個logger對象,如果沒有指定名字將返回root logger)
一個最簡單的過程:
import
logging
logger
=
logging
.
getLogger
(
)
# 創建一個handler,用于寫入日志文件
fh
=
logging
.
FileHandler
(
'test11.log'
,
mode
=
'w'
)
# 再創建一個handler,用于輸出到控制臺
ch
=
logging
.
StreamHandler
(
)
formatter
=
logging
.
Formatter
(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
fh
.
setFormatter
(
formatter
)
ch
.
setFormatter
(
formatter
)
logger
.
addHandler
(
fh
)
#logger對象可以添加多個fh和ch對象
logger
.
addHandler
(
ch
)
logger
.
setLevel
(
logging
.
DEBUG
)
#設置日志的級別。對于低于該級別的日志消息將被忽略.
logger
.
debug
(
'logger debug message'
)
logger
.
info
(
'logger info message'
)
logger
.
warning
(
'logger warning message'
)
logger
.
error
(
'logger error message'
)
logger
.
critical
(
'logger critical message'
)
-
FileHandler(StreamHandler):
A handler class which writes formatted logging records to disk files.
def init (self, filename, mode=‘a’, encoding=None, delay=False): -
logging庫提供了多個組件:
Logge
r、Handler
、Filter
、Formatter
。Logger對象提供應用程序可直接使用的接口,Handler發送日志到適當的目的地,Filter提供了過濾日志信息的方法,Formatter指定日志顯示格式。 -
Logger是一個樹形層級結構,輸出信息之前都要獲得一個Logger(如果沒有顯示的獲取則自動創建并使用root Logger,)。 logger = logging.getLogger()返回一個默認的Logger也即root Logger,并應用默認的日志級別、Handler和Formatter設置。
當然也可以通過Logger.setLevel(lel)
指定最低的日志級別,可用的日志級別有logging.DEBUG、``logging.INFO
、logging.WARNING
、logging.ERROR
、logging.CRITICAL
。 -
Logger.debug()
、Logger.info()
、Logger.warning()
、Logger.error()
、Logger.critical()
輸出不同級別的日志,只有日志等級大于或等于設置的日志級別的日志才會被輸出
可以將上述logging進行函數化
import
logging
def
logger
(
)
:
logger
=
logging
.
getLogger
(
)
# 創建一個handler,用于寫入日志文件
fh
=
logging
.
FileHandler
(
'test10.log'
,
mode
=
'w'
)
# 再創建一個handler,用于輸出到控制臺
ch
=
logging
.
StreamHandler
(
)
formatter
=
logging
.
Formatter
(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
fh
.
setFormatter
(
formatter
)
ch
.
setFormatter
(
formatter
)
logger
.
addHandler
(
fh
)
#logger對象可以添加多個fh和ch對象
logger
.
addHandler
(
ch
)
logger
.
setLevel
(
logging
.
DEBUG
)
#設置日志的級別。對于低于該級別的日志消息將被忽略.
return
logger
logger
=
logger
(
)
logger
.
debug
(
'logger debug message'
)
logger
.
info
(
'logger info message'
)
logger
.
warning
(
'logger warning message'
)
logger
.
error
(
'logger error message'
)
logger
.
critical
(
'logger critical message'
)
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
