<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
紀錄檔是個好東西,但卻並不是所有人都願意記,直到出了問題才追悔莫及,長嘆一聲,當初要是記紀錄檔就好了。
但記紀錄檔卻是個技術活,不能什麼都不記,但也不能什麼都記。如果記了很多沒用的資訊,反而給查紀錄檔排錯的過程增加很多困難。
所以,紀錄檔要記錄在程式的關鍵節點,而且內容要簡潔,傳遞資訊要準確。要清楚的反應出程式當時的狀態,時間,錯誤資訊等。
只有做到這樣,我們才能在第一時間找到問題,並且解決問題
開發階段,所有的問題都可以通過偵錯,在程式中輸出,但專案上線後,會進行統一的錯誤處理,不能將錯誤資訊暴漏出來,所以最好的方式,就是將程式執行資訊儲存在紀錄檔中
程式上線後,是萬萬不能沒有紀錄檔的
Django 使用 Python 內建的 logging
模組處理系統紀錄檔,所以,只要掌握了 Python 中的 logging
模組,基本也就能夠在 django 中使用紀錄檔了
這裡簡單介紹 Python 中 logging
模組的使用,下一章再聊如何在 django 中使用
logging 模組的使用主要包含如下幾個方面
首先匯入 logging 模組,然後在下面選擇方法進行紀錄檔輸出
級別 | 何時使用 |
---|---|
DEBUG | 細節資訊,僅當診斷問題時適用。 |
INFO | 確認程式按預期執行。 |
WARNING | 表明有已經或即將發生的意外(例如:磁碟空間不足)。程式仍按預期進行。 |
ERROR | 由於嚴重的問題,程式的某些功能已經不能正常執行 |
CRITICAL | 嚴重的錯誤,表明程式已不能繼續執行 |
簡單例子
logging.debug('出現了bug') logging.info('一般資訊') logging.warning('警告資訊以下級別預設不出現') logging.error('出現了錯誤') logging.critical('嚴重問題')
紀錄檔資訊,被直接輸出出來,並沒有記錄到紀錄檔中
上面的 logging.info('一般資訊')
和 logging.debug('出現了bug')
並沒有任何輸出,原因在於 logging 模組預設只輸出 WARNING以上級別(包含 WARNING)
通過 basicConfig
方法更改紀錄檔級別
# 更改紀錄檔級別 logging.basicConfig(level=logging.INFO) logging.info('一般資訊') logging.debug('出現了bug') logging.warning('警告資訊以下級別預設不出現') logging.error('出現了錯誤') logging.critical('嚴重問題')
級別 INFO 高於 DEBUG,如果希望 logging.debug
方法生效,需要更改 level 為 logging.DEBUG
實際開發中,紀錄檔資訊一定要儲存到檔案的
basicConfig
方法頁可以設定紀錄檔檔案的目錄資訊
修改案例中第1行程式碼,新增 filename
引數,設定紀錄檔檔案目錄和名稱
logging.basicConfig(filename='0707.log', level=logging.INFO)
開啟紀錄檔檔案,發現亂碼了
basicConfig
方法頁可以設定紀錄檔檔案編碼
logging.basicConfig(filename='0707.log', encoding='utf-8', level=logging.INFO)
預設情況下,新的紀錄檔內容採用的是追加模式
可以通過 filemode
引數設定覆蓋之前的紀錄檔內容
logging.basicConfig(filename='0707.log', filemode='w', encoding='utf-8', level=logging.INFO)
basicConfig()
被設計為一次性的設定,只有第一次呼叫會進行操作,隨後的呼叫不會產生有效操作
此段的意思是,當程式啟動後,第一次呼叫上面的方法,會生效,後面如果程式沒有重新啟動,無論呼叫多少次,此程式碼都不會生效
看下面程式碼
logging.basicConfig(filename='0707.log', filemode='w', encoding='utf-8', level=logging.INFO) logging.info('一般資訊')
啟動程式,或者修改程式碼儲存時也會熱過載,此時紀錄檔檔案內容就會被覆蓋
但在沒有重啟的情況下,無論上面程式碼執行多少次,都不會覆蓋內容,而是追加
此種模式的意義在於:程式重啟後,舊的紀錄檔對於我們沒有意義的情況
可以使用下面兩種方式進行變數的格式化
logging.basicConfig(filename='0707.log', filemode='w', encoding='utf-8', level=logging.INFO) logging.info('採用 %s 的方式輸出變數', '%s') logging.info('採用{}的方式輸出變數'.format('format'))
這是預設情況下紀錄檔訊息的組成
如果想更改,可以通過 basicConfig
方法的 format 引數設定
logging.basicConfig(format='%(levelname)s:%(message)s', filename='0707.log', filemode='w', encoding='utf-8', level=logging.INFO) logging.info('採用 %s 的方式輸出變數', '%s') logging.info('採用{}的方式輸出變數'.format('format'))
下面只顯示級別和紀錄檔內容,沒有 root
程式碼中levelname
和 message
LogRecord
的屬性,完整屬性列表如下
args | 此屬性不需要使用者進行格式化。 | 合併到 msg 以產生 message 的包含引數的元組,或是其中的值將被用於合併的字典(當只有一個引數且其型別為字典時)。 |
---|---|---|
asctime | %(asctime)s | 表示人類易讀的 LogRecord 生成時間。 預設形式為 ‘2003-07-08 16:49:45,896’ (逗號之後的數位為時間的毫秒部分)。 |
created | %(created)f | LogRecord 被建立的時間(即 time.time() 的返回值)。 |
exc_info | 此屬性不需要使用者進行格式化。 | 異常元組(例如 sys.exc_info )或者如未發生異常則為 None 。 |
filename | %(filename)s | pathname 的檔名部分。 |
funcName | %(funcName)s | 函數名包括呼叫紀錄檔記錄. |
levelname | %(levelname)s | 訊息文字記錄級別('DEBUG' ,'INFO' ,'WARNING' ,'ERROR' ,'CRITICAL' )。 |
levelno | %(levelno)s | 訊息數位的記錄級別 (DEBUG , INFO , WARNING , ERROR , CRITICAL ). |
lineno | %(lineno)d | 發出紀錄檔記錄呼叫所在的源行號(如果可用)。 |
message | %(message)s | 記入紀錄檔的訊息,即 msg % args 的結果。 這是在發起呼叫 Formatter.format() 時設定的。 |
module | %(module)s | 模組 (filename 的名稱部分)。 |
msecs | %(msecs)d | LogRecord 被建立的時間的毫秒部分。 |
msg | 此屬性不需要使用者進行格式化。 | 在原始紀錄檔記錄呼叫中傳入的格式字串。 與 args 合併以產生 message ,或是一個任意物件 (參見 使用任意物件作為訊息)。 |
name | %(name)s | 用於記錄呼叫的紀錄檔記錄器名稱。 |
pathname | %(pathname)s | 發出紀錄檔記錄呼叫的原始檔的完整路徑名(如果可用)。 |
process | %(process)d | 程序ID(如果可用) |
processName | %(processName)s | 程序名(如果可用) |
relativeCreated | %(relativeCreated)d | 以毫秒數表示的 LogRecord 被建立的時間,即相對於 logging 模組被載入時間的差值。 |
stack_info | 此屬性不需要使用者進行格式化。 | 當前執行緒中從堆疊底部起向上直到包括紀錄檔記錄呼叫並引發建立當前記錄堆疊幀建立的堆疊幀資訊(如果可用)。 |
thread | %(thread)d | 執行緒ID(如果可用) |
threadName | %(threadName)s | 執行緒名(如果可用) |
比如,修改上面程式碼,加上 asctime
屬性
logging.basicConfig(format='%(levelname)s:%(message)s:%(asctime)s', filename='0707.log', filemode='w', encoding='utf-8', level=logging.INFO)
檢視紀錄檔
上面介紹的方法已經可以為程式設定紀錄檔功能了
logging
模組頁提供了模組化的方法,通過下面幾個元件來設定紀錄檔
其實完成的還是上面的功能,只不過可以進行模組化拆分,比如可以建立多個處理器,多個格式器,通過設定的方式進行處理器、格式器的切換
# 建立記錄器 logger = logging.getLogger('simple') # 設定紀錄檔記錄級別 logger.setLevel(logging.DEBUG) # 建立處理器 ch = logging.StreamHandler() # 設定處理器級別 ch.setLevel(logging.DEBUG) # 建立格式器 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 為處理器設定格式器 ch.setFormatter(formatter) # 將處理器新增到記錄器 logger.addHandler(ch) logger.debug('debug message') logger.info('info message') logger.warning('warn message') logger.error('error message') logger.critical('critical message')
總結:
①:建立記錄器:記錄器中提供了 info、debu
、warning、error、critical 方法用來記錄紀錄檔
②:設定記錄器級別:此級別了哪個級別以上的資訊會被記錄到紀錄檔中
③:建立處理器:處理器決定如何處理訊息、比如列印到控制檯、寫入紀錄檔檔案、傳送郵件等
④:設定處理器級別:決定處理器傳送哪些訊息。記錄器中設定的級別,決定哪個級別以上的訊息會被傳送給處理器,處理器中的設定級別決定了,哪些訊息會被處理,比如哪些訊息會被寫到檔案中。
⑤:建立格式器:決定紀錄檔的格式和紀錄檔中包含哪些內容
⑥:將格式器新增到處理器:處理器將使用此格式器格式化紀錄檔
⑦:將處理器新增到記錄器:記錄器將使用此處理器處理紀錄檔
如果希望紀錄檔儲存到檔案中,只需重新建立一個處理器,將其新增到記錄器中即可
# 建立控制器,將紀錄檔寫入到檔案中 ch_file = logging.FileHandler('aa.log') ch_file.setLevel(logging.DEBUG) # 為處理器設定格式器 ch_file.setFormatter(formatter) # 將處理器新增到記錄器 logger.addHandler(ch_file)
Python 3.2中引入的一種新的設定紀錄檔記錄的方法–用字典來儲存logging設定資訊。這相對於上面所講的基於組態檔來儲存logging設定資訊的方式來說,功能更加強大,也更加靈活,因為我們可把很多的資料轉換成字典。比如,我們可以使用JSON格式的組態檔、YAML格式的組態檔,然後將它們填充到一個設定字典中;或者,我們也可以用Python程式碼構建這個設定字典,或者通過socket接收pickled序列化後的設定資訊。總之,你可以使用你的應用程式可以操作的任何方法來構建這個設定字典
編寫設定字典,然後通過 logging.config.dictConfig
方法呼叫此字典
1、簡單設定
# 用於格式化 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' log_dict = { "version": 1, 'disable_existing_loggers': False, "formatters": { "simple": { 'format': simple_format } }, "handlers": { "console": { "class": 'logging.StreamHandler', "level": 'INFO', "formatter": "simple" } }, "loggers": { "simple": { "level": "DEBUG", "handlers": ['console'], 'propagate': True, } } } logging.config.dictConfig(log_dict) logger = logging.getLogger('simple') logger.debug('debug message') logger.info('info message') logger.warning('warn message') logger.error('error message') logger.critical('critical message')
①:建立了一個名為 simple 的格式器
②:建立了一個名為 console 的處理器,並設定處理器使用的格式器為 simple
③:建立了額一個名為 simple 的記錄器,並設定記錄器使用的處理器為 console
2、增加新的格式器、處理器和記錄器
建立一個新的格式器
standard = '%(levelname)s:%(asctime)s:%(filename)s:%(lineno)d:%(message)s'
新增
建立新的處理器,用於將紀錄檔寫入檔案
在記錄器中新增此處理器
執行程式,紀錄檔將同時列印到控制檯和紀錄檔檔案中
這裡應該體會到了使用設定字典的好處
建立記錄器時,選擇 standard
,則只會輸出 ERROR 以上的紀錄檔資訊
3、組態檔-yaml
開發時,最好的方式,當然不是在程式中編寫程式碼做出上面設定
而是,新建組態檔,程式執行時,讀取組態檔
我們將設定寫到一個 yaml ,然後讀取此檔案
根目錄下新建 log_config.yml (yaml 檔案的字尾名可以是yaml 或者 yml)
version: 1 formatters: simple: format: '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' standard: format: '%(levelname)s:%(asctime)s:%(filename)s:%(lineno)d:%(message)s' handlers: console: class: logging.StreamHandler level: DEBUG formatter: simple file: class: logging.FileHandler formatter: simple filename: logtest.log loggers: simple: level: DEBUG handlers: [ file ] propagate: True standard: level: ERROR handlers: [ console,file ] propagate: True
檢視函數程式碼,讀取 yaml 檔案,並將其轉換成 dict,使用 logging.config.dictConfig
方法載入設定,並使用其中名稱為 simple
的記錄器
BASE_DIR = Path(__file__).resolve().parent.parent with open(str(BASE_DIR) + 'config.yaml', 'r', encoding='utf-8') as f: file = f.read() config = yaml.load(file, Loader=yaml.FullLoader) logging.config.dictConfig(config) logger = logging.getLogger('simple') logger.debug('debug message') logger.info('info message') logger.warning('warn message') logger.error('error message') logger.critical('critical message')
切換記錄器,看看效果
練習:自己再設定幾個處理器和格式器
4、寫到 settings 中
也可以將上面的設定直接寫到 settings.py 中
變數名稱必須為 LOGGING
# 紀錄檔設定 LOGGING = { "version": 1, "formatters": { "simple": { "format": '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' }, "standard": { "format": '%(levelname)s:%(asctime)s:%(filename)s:%(lineno)d:%(message)s' } }, "handlers": { "console": { "class": "logging.StreamHandler", "level": "DEBUG", "formatter": "simple" }, "file": { "class": "logging.FileHandler", "formatter": "simple", "filename": "logtest.log" } }, "loggers": { "simple": { "level": "DEBUG", "handlers": ["file"], "propagate": True }, "standard": { "level": "ERROR", "handlers": ["console", "file"], "propagate": True } } }
檢視函數
logger = logging.getLogger('simple') logger.debug('debug message') logger.info('info message') logger.warning('warn message') logger.error('error message') logger.critical('critical message')
上面介紹了 Python 中使用紀錄檔的方式,有了這些基礎之後,學習 django 中紀錄檔的使用就事半功倍了
django 中仍然使用了 logging
模組做紀錄檔處理
其實,3.8 節已經講完了,就是這麼用。。。。
附:關於 logging 模組的詳細說明
在Python的logging模組中,主要包含下面四大方面:
下文詳細說明一下這四大模組
logger 是紀錄檔系統的入口。每個 logger 都是命名了的 bucket, 訊息寫入 bucket 以便進一步處理。
logger 可以設定紀錄檔級別。紀錄檔級別描述了由該 logger 處理的訊息的嚴重性。Python 定義了下面幾種紀錄檔級別:
DEBUG
:排查故障時使用的低階別系統資訊;INFO
:一般的系統資訊;WARNING
:描述系統發生了一些小問題的資訊;ERROR
:描述系統發生了大問題的資訊;CRITICAL
:描述系統發生嚴重問題的資訊;
每一條寫入 logger 的訊息都是一條紀錄檔記錄。每一條紀錄檔記錄也包含紀錄檔級別,代表對應訊息的嚴重程度。紀錄檔記錄還包含有用的後設資料,來描述被記錄的事件細節,例如堆疊跟蹤或者錯誤碼。
當logger處理一條訊息時,會將自己的紀錄檔級別和這條訊息的紀錄檔級別做對比。如果訊息的紀錄檔級別匹配或者高於 logger 的紀錄檔級別,它就會被進一步處理。否則這條訊息就會被忽略掉。
當 logger 確定了一條訊息需要處理之後,會把它傳給Handler。
Handler是決定如何處理logger中每一條訊息的引擎。它描述特定的紀錄檔行為,比如把訊息輸出到螢幕、檔案或網路 socket。
和logger一樣,handler也有紀錄檔級別的概念。如果一條紀錄檔記錄的級別不匹配或者低於handler的紀錄檔級別,對應的訊息會被 handler忽略。
一個logger可以有多個handler,每一個handler可以有不同的紀錄檔級別。這樣就可以根據訊息的重要性不同,來提供不同格式的輸出。例如,你可以新增一個 handler 把ERROR和CRITICAL訊息發到尋呼機,再新增另一個handler把所有的訊息(包括 ERROR和CRITICAL訊息)儲存到檔案裡以便日後分析。
在紀錄檔從 logger 傳到 handler 的過程中,使用 Filter 來做額外的控制。
預設情況下,只要級別匹配,任何紀錄檔訊息都會被處理。不過,也可以通過新增filter來給紀錄檔處理的過程增加額外條件。例如,可以新增一個filter只允許某個特定來源的ERROR訊息輸出。
Filter還被用來在紀錄檔輸出之前對紀錄檔記錄做修改。例如,可以寫一個filter,當滿足一定條件時,把紀錄檔記錄從ERROR降到 WARNING級別。
Filter在logger和handler中都可以新增;多個filter可以連結起來使用,來做多重過濾操作。
紀錄檔記錄最終是需要以文字來呈現的。Formatter 描述了文字的格式。一個 formatter 通常由包含 LogRecord attributes 的 Python 格式化字串組成,不過你也可以為特定的格式來設定自定義的 formatter。
到此這篇關於django 中使用紀錄檔的文章就介紹到這了,更多相關django 使用紀錄檔內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45