python中的logging
Ⅰ python程序中logging怎麼用
簡單將日誌列印到屏幕:
[python] view plain
import logging
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
輸出:
WARNING:root:warning message
ERROR:root:error message
CRITICAL:root:critical message
可見,默認情況下Python的
logging模塊將日誌列印到了標准輸出中,且只顯示了大於等於WARNING級別的日誌,這說明默認的日誌級別設置為WARNING(日誌級別等級
CRITICAL > ERROR > WARNING > INFO > DEBUG >
NOTSET),默認的日誌格式為日誌級別:Logger名稱:用戶輸出消息。
靈活配置日誌級別,日誌格式,輸出位置
[python] view plain
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='/tmp/test.log',
filemode='w')
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
查看輸出:
cat /tmp/test.log
Mon, 05 May 2014 16:29:53 test_logging.py[line:9] DEBUG debug message
Mon, 05 May 2014 16:29:53 test_logging.py[line:10] INFO info message
Mon, 05 May 2014 16:29:53 test_logging.py[line:11] WARNING warning message
Mon, 05 May 2014 16:29:53 test_logging.py[line:12] ERROR error message
Mon, 05 May 2014 16:29:53 test_logging.py[line:13] CRITICAL critical message
可見在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參數會被忽略。
format參數中可能用到的格式化串:
%(name)s Logger的名字
%(levelno)s 數字形式的日誌級別
%(levelname)s 文本形式的日誌級別
%(pathname)s 調用日誌輸出函數的模塊的完整路徑名,可能沒有
%(filename)s 調用日誌輸出函數的模塊的文件名
%(mole)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用戶輸出的消息
Ⅱ python 中 logging.info是干嗎的
logging是python的日誌庫,是一個類
info是logging的一個屬性
logging.info是輸出日誌的信息
logging.info('輸出信息')
Ⅲ logging:多線程調試時用來代替print和單步調試
當你要寫多線程項目時,不免要調試錯誤,要debug。
一般debug的工具就是列印函數print, 調試工具gdb進行單步調試,但是多線程時,單步調試就很雞肋了,這時就需要列印日誌了
沒錯,列印日誌無疑是調試多線程工程的高效工具了。
在python中開發,就要用到logging日誌庫了
logging庫已經封裝好日誌需要的基本功能,能夠實現在文件里,在命令行等寫日誌
還能輸出日誌信息的類型,如debug,warning,error等
細節在這里有所介紹:
https://docs.python.org/3/howto/logging.html
文本介紹一下,第一次使用logging時,要熟悉logging時,需要用一個非常簡單的例子
先看一個最簡單的例子:
運行以上代碼:
printed out on the console. The INFO message doesn』t appear because the default level is WARNING . The printed message includes the indication of the level and the description of the event provided in the logging call, i.e. 『Watch out!』. Don』t worry about the 『root』 part for now: it will be explained later. The actual output can be formatted quite flexibly if you need that; formatting options will also be explained later.
輸出結果為:
如果你想每次都在一個新的日誌文件中寫日誌,那麼使用filemode='w'參數:
分別在main 函數里,在mylib.py里寫日誌
運行後的輸出:
以上代碼會顯示:
該 format參數的值
以上代碼會顯示:
還是該format:
以上代碼會輸出
如果想自己設定時間的格式:
會這樣顯示:
logging庫中用了模塊化的思路,把日誌的整體功能用了4個基本的模塊來完成:
Loggers,Handlers,Filters,Formatters
其中,Handlers,主要配置將信息寫到命令行,還是寫到文件里。
Filters,是對信息本身的過濾,決定那些信息不寫,那些信息寫。
Formatters決定信息輸出的格式。比如是否輸出時間,是否輸出logger本身的名字等,決定那些信息在前,那些信息在後等。
Logger就是Handler,Filter,Formatter配置的一個日誌對象了。
下面我們逐個說一下這4個類:
它有三個功能,1 提供分級日誌的輸出,比如 WARNING,ERROR,INFO等不同等級。2. 它可以決定哪些信息輸出,哪些信息不輸出。3 它可以將一條信息發給命令行和文件,可以把一條信息發給多個handler去處理。
logger 最常用的成員方法大概分兩類:配置和信息發送
以下是常用的配置函數:
Logger.setLevel() 設定信息記錄的等級。如果一條信息的等級比我們設定的低,那麼就不對此條信息進行處理。信息一共分為:DEBUG,INFO,WARNING,ERROR,CRITICAL 五個級別,其中DEBUG是最低的等級,CRITICAL是最高的等級。
Logger.addHandler() 和 Logger.removeHandler(),添加或者刪除信息處理器Handler。這個信息處理器就是定義了將日誌寫入命令行,還是寫入文件,或者寫入郵件等。
Logger.addFilter() 和 Logger.removeFilter() .添加或者刪除信息過濾器Filter。這個信息過濾器,決定了哪些信息不顯示。
可以看到,信息過濾器,信息處理器,信息等級共同配置了logger.
並不是每個logger你都需要去配置一遍,你可以利用logger的繼承機制,只配置父logger.
一旦配置好logger之後,就可以用以下函數來在你自己代碼的任意位置來記錄日誌了。
Logger.debug(),Logger.info(),Logger.warning(),Logger.error()和Logger.critical.這些函數的功能都是建立了日誌記錄信息,不同的是,函數名字就代表了其建立的日誌信息的等級。
Logger.exeception()建立一個與Logger.error()比較相似的信息。但是Logger.exception()是放入一個追蹤盞裡面的。所以,只有在exception handler處理器中,才能使用它。
Logger.log()發送一個LOG 等級的信息,使用LOG等級的信息稍微繁瑣些,因為使用LOG等級可以自定義等級。
getLogger() 返回一個logger的引用,如果指定了名字,那麼返回特定名字對應的logger,如果沒有指定名字,那就返回一個名字為root的loger的引用名字root,或者你指定的名字是一種級連結構。用同樣的名字去調用getLogger(),會得到同樣的值。logger的名字也決定了logger在樹結構中的層級。例如:這里有一個logger的名字為foo,那麼foo.bar,foo.bar.baz,還有foo.bam都是foo的子孫,logger還有一個有效等級level的概念。這個有效等級其實就是決定debug,info,warning等不同類型的消息是否進行記錄。因為logger本身有了父子那樣的繼承關系,所以有效等級level也是可以繼承的。如果子logger沒有設定了自身的level,那麼就把父logger的level繼承過來使用。如果子logger本身設定了level,就用自身這個level.如果父logger仍然沒有設定level,那就看父logger的父logger,一直這么追述下去,就會追述到root上,所以,我們必須給root設定一個level,或者默認一個level,方便root的子logger去繼承。我們給root設定的默認levle為WARNING.如果有些日誌的level,相比我們設定的WARNING低,那麼它就不會被傳遞給Handler去處理,就不會被列印出來,或者記錄進日誌文件。另外logger的屬性也是可繼承的,所以就只配置一下root logger即可,沒有root logger時,只用配置一個相對的那個根logger就行了
handler 信息處理器是負責信息分發給不同的目的地的,這個目的地可能是命令行,也可能是文件,或者郵件。分發時,同樣要檢查信息本身的等級severity.一個logger可以用addHandler()函數添加0個或者多個handlers。比如有這樣一個場景,希望發送所有的log等級的信息到一個log文件內。所有的等級為錯誤的信息到stdout 標准輸出上,發送所有的critical信息到郵件上。這樣的場景需要3個不同的處理器,每個處理器負責發送相應等級的信息到相應的目的地。
標准庫里包含一些處理器類型,本教程主要使用StreamHandler 和 FileHandler兩種信息處理器。
處理器中的成員函數非常少,我們用來配置處理器的成員函數大概有這個幾個:
setLevel(),用來設置處理器處理的信息等級。注意到logger中有setLevel(),而處理器中也有setLevel(),也就是說,logger把信息通過信息等級過濾一遍後,logger內的處理器需要根據處理器自身的功能設定,再根據信息等級來過濾一遍。
setFormatter() 為處理器設定一種信心記錄的格式Formatter
addFilter() removeFilter()函數添加信息過濾器或者刪除信息過濾器的函數。
到這里,我們發現,logger類中,將信息發送到不同的目的地就依賴Handlers實現的,
所有Handler就需要用Formatter和Filter來配置一下。接下來,我們看看Formatter和Filter.
它決定了信息顯示的順序,結構和內容。可以直接操作formatter的相關類,也可以自己繼承 formatter類,去完成自己的設定。formatter的構造函數需要3個可選的參數:字元串格式的信息,日期,一個符號。
logging.Formatter.__init__(fmt=None,datafmt=None,style='%')
如果這里沒有設定參數,就使用默認參數。對於fmt來說,就顯示原來信息,對於datafmt來說,就以年-月-日 時:分:秒的合適顯示。
下面的fmt就定義了一個按照 時間-信息等級-信息本身 來記錄日誌的方法:
這里有三種方法:
寫代碼配置logging的例子:
運行結果為:
寫配置文件配置logging的例子:
代碼中所需要的配置文件ogging.conf的具體內容為 :
以上代碼的輸出為:
顯然,配置文件修改起來相對容易很多。
還有更方便的配置方式,使用字典來配置:
運行結果與上面一樣。
到這里,基本完成了logging庫的比較常用的使用方式。
比如在什麼情況下,需要使用一個什麼都不做的處理器NullHandler(),
還有關於信息等級的更詳細的解釋:
以及如何自定義信息等級。
還有關於異常的處理
還有關於信息的,信息都是字元串的。不過你也可以直接把某個類作為信息拋出來,因為類會自動調用其__str__()函數,返回一個類的字元串回來。
還有就是優化性能的一些小技巧
這里就編寫expensive_func1 和 expensive_func2 來完成設定數據格式。
以下表格也顯示了如何收集運行log的代碼文件信息,線程信息,進程信息,處理器信息
以及如何操作才能收集代碼文件信息,線程信息,進程信息,以及處理器信息。
我們一般會使用收集代碼文件,線程,進程等信息,因為這樣大大方便了多線程多進程工程的調試。
Ⅳ 多進程環境python logging列印日誌混亂問題
解決辦法如下:
多麼痛的領悟,困擾了這么久的問題其實就是一個參數配置錯了。
fileMode:表示日誌文件的打開方式。w-直接寫,使用這個配置當系統重啟的時候日誌會清空,一個進程打開後其他進程是無法使用的;a-尾部追加,大家都可以打開往文件結尾進行追加寫入。
本人主語言是java,轉到python後日誌這塊踩了幾個坑。再說說另外一個坑,就是異常堆棧的列印問題,在java中logger是可以使用error直接列印出來的。在python中error跟其他日誌記錄方法沒太大差別,是無法列印異常堆棧的,列印堆棧請使用 logger.exception("異常說明", e) 。
Ⅳ 在 python 項目中如何記錄日誌
寫本文的目的是我在寫 python 項目的時候需要記錄日誌,我忘記怎麼處理了,每次都需要去網上查一遍, 好記性不如爛筆頭 , 這里把查閱的內容記錄下來,方便以後查找。
python 項目中記錄日誌,可以使用 logging 模塊,logging 模塊定義的函數和類為應用程序和庫的開發實現了一個靈活的事件日誌系統。logging 模塊是Python的一個標准庫模塊,由標准庫模塊提供日誌記錄API的關鍵好處是所有Python模塊都可以使用這個日誌記錄功能。所以,你的應用日誌可以將你自己的日誌信息與來自第三方模塊的信息整合起來。
在 __init__.py 文件中做如下配置:
控制台輸出日誌如下:
參考文檔
https://www.cnblogs.com/yyds/p/6901864.html
Ⅵ Python日誌—Python日誌模塊logging介紹
從事與軟體相關工作的人,應該都聽過「日誌」一詞。
日誌就是跟蹤軟體運行時事件的方法,為了能夠在程序運行過程中記錄錯誤。
通過日誌記錄程序的運行,方便我們查詢信息,以便追蹤問題、進行維護和調試、還是數據分析。
並且各編程語言都形成了各自的日誌體系和相應的框架。
日誌的作用總結:
首先我們要樹立一個觀點,那就是「不是為了記錄日誌而記錄日誌,日誌也不是隨意記的」。要實現能夠只通過日誌文件還原整個程序執行的過程,達到能透明地看到程序里執行情況,每個線程每個過程到底執行結果的目的。日誌就像飛機的黑匣子一樣,應當能夠復原異常的整個現場乃至細節。
在項目中,日誌這個功能非常重要,我們要重視起來。
在Python中,使用logging模塊來進行日誌的處理。
logging是Python的內置模塊,主要用於將日誌信息進行格式化內容輸出,可將格式化內容輸出到文件,也可輸出到屏幕。
我們在開發過程中,常用print()函數來進行調試,但是在實際應用的部署時,我們要將日誌信息輸出到文件中,方便後續查找以及備份。
在我們使用日誌管理時,我們也可以將日誌格式化成Json對象轉存到ELK中方便圖形化查看及管理。
logging模塊將日誌系統從高向低依次定義了四個類,分別是logger(日誌器)、handler(處理器)、filter(過濾器)和formatter(格式器)。其中由日誌器生成的實例將接管原本日誌記錄函數logging.log的功能。
說明:
我們先來思考下下面的兩個問題:
在軟體開發階段或部署開發環境時,為了盡可能詳細的查看應用程序的運行狀態來保證上線後的穩定性,我們可能需要把該應用程序所有的運行日誌全部記錄下來進行分析,這是非常耗費機器性能的。
當應用程序正式發布或在生產環境部署應用程序時,我們通常只需要記錄應用程序的異常信息、錯誤信息等,這樣既可以減小伺服器的I/O壓力,也可以避免我們在排查故障時被淹沒在日誌的海洋里。
那麼怎樣才能在不改動應用程序代碼的情況下,根據事件的重要性或者稱之為等級,實現在不同的環境中,記錄不同詳細程度的日誌呢?
這就是日誌等級的作用了,我們通過配置文件指定我們需要的日誌等級就可以了。
說明:
總結:
開發應用程序時或部署開發環境時,可以使用DEBUG或INFO級別的日誌獲取盡可能詳細的日誌信息,可以方便進行開發或部署調試。 應用上線或部署生產環境時,應用使用WARNING或ERROR或CRITICAL級別的日誌,來降低機器的I/O壓力和提高獲取錯誤日誌信息的效率。 日誌級別的指定通常都是在應用程序的配置文件中進行指定的。 不同的應用程序所定義的日誌等級會有所差別,根據實際需求來決定。
Ⅶ Python中的logger和handler到底是個什麼鬼
最近的任務經常涉及到日誌的記錄,特意去又學了一遍logging的記錄方法。跟java一樣,python的日誌記錄也是比較繁瑣的一件事,在寫一條記錄之前,要寫好多東西。典型的日誌記錄的步驟是這樣的:
創建logger
創建handler
定義formatter
給handler添加formatter
給logger添加handler
寫成代碼差不多就是醬嬸的(這個是照別的網頁抄的,參考附註):
1 import logging
2
3 # 1、創建一個logger
4 logger = logging.getLogger('mylogger')
5 logger.setLevel(logging.DEBUG)
6
7 # 2、創建一個handler,用於寫入日誌文件
8 fh = logging.FileHandler('test.log')
9 fh.setLevel(logging.DEBUG)
10
11 # 再創建一個handler,用於輸出到控制台
12 ch = logging.StreamHandler()
13 ch.setLevel(logging.DEBUG)
14
15 # 3、定義handler的輸出格式(formatter)
16 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
17
18 # 4、給handler添加formatter
19 fh.setFormatter(formatter)
20 ch.setFormatter(formatter)
21
22 # 5、給logger添加handler
23 logger.addHandler(fh)
24 logger.addHandler(ch)
之後才可以正式的開始記錄日誌。Java裡面的java.util.Logging類差不多也是這樣,代碼還要更復雜一點。Golang的日誌相對
寫法簡單一些,不過沒有什麼格式,系統記錄一條時間,內容格式完全自己手畫。第三方的日誌庫倒是沒有接觸過,像Java的Log4j,Golang的
log4go和seelog等等,不知道用起來會不會簡單一點。我一直都記不住這些,因為不太理解logger和handler為什麼要這樣寫。一直到這
次任務中出現的在我看來相當「詭異」的bug,才深入理解了一下。
我的任務是這樣的,要做一個日誌切割的工具,按天將日誌分割開,即每天0點產生一個新日誌,將舊日誌改名。並且,將超過3個月的日誌刪除掉,以保證磁碟空間不會被log占滿。程序要求可以切割多個目錄中的不同日誌,具體路徑由json中配置。
這里用到了logging.handlers類中的TimedRotatingFileHandler方法,用以獲得一個handler。大概的寫法為:
1 logger = logging.getLogger() #獲得logger
2 handler = logging.handlers.TimedRotatingFileHandler(logfile, 'S', 1, 0) #切割日誌
3 handler.suffix = '%Y%m%d' #切割後的日誌設置後綴
4 logger.addHandler(handler) #把logger添加上handler
5 logger.fatal(datetime.datetime.now().strftime('%Y-%m-%d')) #在新日誌中寫上當天的日期
這里我沒有設置level和formatter。因為只是分割,對新日誌沒有什麼影響。TimedRotatingFileHandler函數的方
法見附註,或查看python的源碼,這個函數是python寫的,可以找到定義。這里我使用的是每秒生成一個新的日誌文件,之後用Crontab在每天
0點調度,然後用for循環處理json中的每一個日誌文件。
但是奇怪的是,每次運行程序,第一個切割的日誌生成一個分割後的文件,而後面的都生成兩個新日誌。百思不得其解。後檢查代碼覺得,可能是程序中設置
的時間太短了,每秒生成一個文件,有可能一秒鍾處理不完,就生成了兩個。雖然這個說法沒有什麼科學根據,但是還是把
TimedRotatingFileHandler中的第三個參數改成了60,即每60秒生成一個文件。完成,靜靜的等待crontab到時間。
Ⅷ python logging繼承關系
這篇文章主要解析python logging模塊不同logger間日誌級別的繼承關系,以及日誌輸出的機制。
在python的logging模塊中,通過 logging.getLogger() 函數可以獲取到指定的logger,如果沒有指定參數, 那麼返回的是root logger. 通過指定不同的logger名稱,這個函數可以返回指定的logger.這里,logger名字 本身體現了logger的繼承關系,它通過"."分隔父logger和子logger,可以存在很多個".",他們一路繼承下來。
如"a.b"這個logger存在一個父logger"a", 而"a"則從root logger繼承而來。如下圖所示:
每個logger下面可能存在0個或多個handler,handler實現日誌的輸出,每個handler對應一個輸出目標。 通過配置多個handler,可以實現同時輸出到文件,控制台的功能。 同時,每個handler可以定製日誌級別,從而使得某些日誌級別可以只輸出到文件中,而不輸出到控制台。
每個logger都可以設置日誌級別,如果沒有設置,默認是NOSET。當logger的日誌級別是NOSET時,它會按照繼承關系向上層獲取日誌級別, 直到日誌級別不是NOSET,或達到root logger為止。如以上關系,
這個機制在 官方文檔setLevel 中有詳細介紹。
logger中,有一個欄位 propagate ,這個欄位用於控制是否 繼承父logger的handler,默認是繼承。
當這個選項打開時,logger除了將日誌寫入自身的handler外,還會將日誌寫入祖先的handler中。
假設我們往a.b這個logger寫入一條日誌,其過程如下:
這里需要注意的是,logger的日誌級別用於在入口處過濾,handler用於出口處過濾,在propagate的時候,已經過了輸入階段,到達輸出階段, 不需要再判斷上層logger的日誌級別,只判斷handler的級別是否滿足。
轉自: https://lisongmin.github.io/python-logging-inherit/
Ⅸ Python 中 logging 模塊使用詳情
在實際應用中,日誌文件十分重要,通過日誌文件,我們知道程序運行的細節;同時,當程序出問題時,我們也可以通過日誌快速定位問題所在。在我們寫程序時,也可以藉助 logging 模塊的輸出信息來調試代碼。
但是很多人還是在程序中使用print()函數來輸出一些信息,比如:
這樣用的話缺點很明顯,當程序寫好運行時,我們要把這些print()函數刪掉,在簡單的的程序中用還行,當程序比較復雜時,這個辦法很低效。
如果使用 logging 模塊,看看效果
運行結果如下:
你也許會問,這和 print() 函數有什麼區別呢?區別就在於,logging模塊可以通過改變level來控制一些語句是否被輸出,比如當我們把level改成DEBUG級別:
得到輸出如下:
logging 模塊是python自帶的一個包,因此在使用的時候,不必安裝,只需要import即可。有5個level,分別是debug,主要是查看一下程序運行的信息,一般是調試程序要看的信息;info,是我們看程序是否如預料執行的信息;warn,意料之外的,但是不影響程序運行; error 和 critical 就是一些比較嚴重的問題,會影響程序運行。默認leval是warn,這個時候debug級別和info級別就不會被輸出到日誌里了。如果想要看到這些信息,就需要進行一些設置。
我們主要調用 basicConfig(***kwargs*) 這個函數對 logging 進行設置。
常用的參數如下:
我們通過調整format,可以輸出我們想要的格式,比如:
結果是:
這就是在 format 參數中設置了時間的,所以得到了時間,我們可以輸出多種想要的信息
總結:
本文主要介紹了 logging 模塊的基礎用法,除非是自己寫的小腳本中我們使用print()函數,其他情況下最好還是用logging模塊來列印信息,輸出日誌吧。
Ⅹ python的logging模塊格式化輸出到控制台、文件
logger提供了應用程序可以直接使用的介面;
handler將(logger創建的)日誌記錄發送到合適的目的輸出;
filter提供了細度設備來決定輸出哪條日誌記錄;
formatter決定日誌記錄的最終輸出格式。
控制台彩色顯示用到colorama模塊
修改Fore.WHITE即可修改相應的顏色