Django?中使用日志的方法
1. 日志的意義
日志是個好東西,但卻并不是所有人都愿意記,直到出了問題才追悔莫及,長嘆一聲,當初要是記日志就好了。
但記日志卻是個技術(shù)活,不能什么都不記,但也不能什么都記。如果記了很多沒用的信息,反而給查日志排錯的過程增加很多困難。
所以,日志要記錄在程序的關(guān)鍵節(jié)點,而且內(nèi)容要簡潔,傳遞信息要準確。要清楚的反應(yīng)出程序當時的狀態(tài),時間,錯誤信息等。
只有做到這樣,我們才能在第一時間找到問題,并且解決問題
開發(fā)階段,所有的問題都可以通過調(diào)試,在程序中輸出,但項目上線后,會進行統(tǒng)一的錯誤處理,不能將錯誤信息暴漏出來,所以最好的方式,就是將程序運行信息存儲在日志中
程序上線后,是萬萬不能沒有日志的
2. django 中如何處理日志
Django 使用 Python 內(nèi)置的 logging
模塊處理系統(tǒng)日志,所以,只要掌握了 Python 中的 logging
模塊,基本也就能夠在 django 中使用日志了
3. Python 中使用日志
這里簡單介紹 Python 中 logging
模塊的使用,下一章再聊如何在 django 中使用
logging 模塊的使用主要包含如下幾個方面
- 將日志信息直接輸出
- 將日志信息保存到文件中
- 輸出變量到日志中
- 更改消息顯示格式
- 覆蓋日志
- 日志配置
3.1 直接輸出日志信息
首先導入 logging 模塊,然后在下面選擇方法進行日志輸出
級別 | 何時使用 |
---|---|
DEBUG | 細節(jié)信息,僅當診斷問題時適用。 |
INFO | 確認程序按預期運行。 |
WARNING | 表明有已經(jīng)或即將發(fā)生的意外(例如:磁盤空間不足)。程序仍按預期進行。 |
ERROR | 由于嚴重的問題,程序的某些功能已經(jīng)不能正常執(zhí)行 |
CRITICAL | 嚴重的錯誤,表明程序已不能繼續(xù)執(zhí)行 |
簡單例子
logging.debug('出現(xiàn)了bug') logging.info('一般信息') logging.warning('警告信息以下級別默認不出現(xiàn)') logging.error('出現(xiàn)了錯誤') logging.critical('嚴重問題')
日志信息,被直接輸出出來,并沒有記錄到日志中
3.2 設(shè)置日志級別
上面的 logging.info('一般信息')
和 logging.debug('出現(xiàn)了bug')
并沒有任何輸出,原因在于 logging 模塊默認只輸出 WARNING以上級別(包含 WARNING)
通過 basicConfig
方法更改日志級別
# 更改日志級別 logging.basicConfig(level=logging.INFO) logging.info('一般信息') logging.debug('出現(xiàn)了bug') logging.warning('警告信息以下級別默認不出現(xiàn)') logging.error('出現(xiàn)了錯誤') logging.critical('嚴重問題')
級別 INFO 高于 DEBUG,如果希望 logging.debug
方法生效,需要更改 level 為 logging.DEBUG
3.3 保存日志到文件
實際開發(fā)中,日志信息一定要保存到文件的
basicConfig
方法頁可以設(shè)置日志文件的目錄信息
修改案例中第1行代碼,添加 filename
參數(shù),設(shè)置日志文件目錄和名稱
logging.basicConfig(filename='0707.log', level=logging.INFO)
打開日志文件,發(fā)現(xiàn)亂碼了
3.4 設(shè)置編碼
basicConfig
方法頁可以設(shè)置日志文件編碼
logging.basicConfig(filename='0707.log', encoding='utf-8', level=logging.INFO)
3.5 覆蓋日志文件
默認情況下,新的日志內(nèi)容采用的是追加模式
可以通過 filemode
參數(shù)設(shè)置覆蓋之前的日志內(nèi)容
logging.basicConfig(filename='0707.log', filemode='w', encoding='utf-8', level=logging.INFO)
basicConfig()
被設(shè)計為一次性的配置,只有第一次調(diào)用會進行操作,隨后的調(diào)用不會產(chǎn)生有效操作
此段的意思是,當程序啟動后,第一次調(diào)用上面的方法,會生效,后面如果程序沒有重新啟動,無論調(diào)用多少次,此代碼都不會生效
看下面代碼
logging.basicConfig(filename='0707.log', filemode='w', encoding='utf-8', level=logging.INFO) logging.info('一般信息')
啟動程序,或者修改代碼保存時也會熱重載,此時日志文件內(nèi)容就會被覆蓋
但在沒有重啟的情況下,無論上面代碼執(zhí)行多少次,都不會覆蓋內(nèi)容,而是追加
此種模式的意義在于:程序重啟后,舊的日志對于我們沒有意義的情況
3.6 記錄變量到日志
可以使用下面兩種方式進行變量的格式化
logging.basicConfig(filename='0707.log', filemode='w', encoding='utf-8', level=logging.INFO) logging.info('采用 %s 的方式輸出變量', '%s') logging.info('采用{}的方式輸出變量'.format('format'))
3.7 更改顯示消息的組成
這是默認情況下日志消息的組成
如果想更改,可以通過 basicConfig
方法的 format 參數(shù)設(shè)置
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'))
下面只顯示級別和日志內(nèi)容,沒有 root
代碼中levelname
和 message
LogRecord
的屬性,完整屬性列表如下
args | 此屬性不需要用戶進行格式化。 | 合并到 msg 以產(chǎn)生 message 的包含參數(shù)的元組,或是其中的值將被用于合并的字典(當只有一個參數(shù)且其類型為字典時)。 |
---|---|---|
asctime | %(asctime)s | 表示人類易讀的 LogRecord 生成時間。 默認形式為 ‘2003-07-08 16:49:45,896’ (逗號之后的數(shù)字為時間的毫秒部分)。 |
created | %(created)f | LogRecord 被創(chuàng)建的時間(即 time.time() 的返回值)。 |
exc_info | 此屬性不需要用戶進行格式化。 | 異常元組(例如 sys.exc_info )或者如未發(fā)生異常則為 None 。 |
filename | %(filename)s | pathname 的文件名部分。 |
funcName | %(funcName)s | 函數(shù)名包括調(diào)用日志記錄. |
levelname | %(levelname)s | 消息文本記錄級別('DEBUG' ,'INFO' ,'WARNING' ,'ERROR' ,'CRITICAL' )。 |
levelno | %(levelno)s | 消息數(shù)字的記錄級別 (DEBUG , INFO , WARNING , ERROR , CRITICAL ). |
lineno | %(lineno)d | 發(fā)出日志記錄調(diào)用所在的源行號(如果可用)。 |
message | %(message)s | 記入日志的消息,即 msg % args 的結(jié)果。 這是在發(fā)起調(diào)用 Formatter.format() 時設(shè)置的。 |
module | %(module)s | 模塊 (filename 的名稱部分)。 |
msecs | %(msecs)d | LogRecord 被創(chuàng)建的時間的毫秒部分。 |
msg | 此屬性不需要用戶進行格式化。 | 在原始日志記錄調(diào)用中傳入的格式字符串。 與 args 合并以產(chǎn)生 message ,或是一個任意對象 (參見 使用任意對象作為消息)。 |
name | %(name)s | 用于記錄調(diào)用的日志記錄器名稱。 |
pathname | %(pathname)s | 發(fā)出日志記錄調(diào)用的源文件的完整路徑名(如果可用)。 |
process | %(process)d | 進程ID(如果可用) |
processName | %(processName)s | 進程名(如果可用) |
relativeCreated | %(relativeCreated)d | 以毫秒數(shù)表示的 LogRecord 被創(chuàng)建的時間,即相對于 logging 模塊被加載時間的差值。 |
stack_info | 此屬性不需要用戶進行格式化。 | 當前線程中從堆棧底部起向上直到包括日志記錄調(diào)用并引發(fā)創(chuàng)建當前記錄堆棧幀創(chuàng)建的堆棧幀信息(如果可用)。 |
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)
查看日志
3.8 模塊化
上面介紹的方法已經(jīng)可以為程序配置日志功能了
logging
模塊頁提供了模塊化的方法,通過下面幾個組件來配置日志
- 記錄器:暴露了應(yīng)用程序代碼直接使用的接口
- 處理器:將日志記錄(由記錄器創(chuàng)建)發(fā)送到適當?shù)哪繕?/li>
- 過濾器:提供了更細粒度的功能,用于確定要輸出的日志記錄
- 格式器:指定最終輸出中日志記錄的樣式
其實完成的還是上面的功能,只不過可以進行模塊化拆分,比如可以創(chuàng)建多個處理器,多個格式器,通過配置的方式進行處理器、格式器的切換
3.8.1 通過 Python 方法配置
# 創(chuàng)建記錄器 logger = logging.getLogger('simple') # 設(shè)置日志記錄級別 logger.setLevel(logging.DEBUG) # 創(chuàng)建處理器 ch = logging.StreamHandler() # 設(shè)置處理器級別 ch.setLevel(logging.DEBUG) # 創(chuàng)建格式器 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 為處理器設(shè)置格式器 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')
總結(jié):
①:創(chuàng)建記錄器:記錄器中提供了 info、debu
、warning、error、critical 方法用來記錄日志
②:設(shè)置記錄器級別:此級別了哪個級別以上的信息會被記錄到日志中
③:創(chuàng)建處理器:處理器決定如何處理消息、比如打印到控制臺、寫入日志文件、發(fā)送郵件等
④:設(shè)置處理器級別:決定處理器發(fā)送哪些消息。記錄器中設(shè)置的級別,決定哪個級別以上的消息會被發(fā)送給處理器,處理器中的設(shè)置級別決定了,哪些消息會被處理,比如哪些消息會被寫到文件中。
⑤:創(chuàng)建格式器:決定日志的格式和日志中包含哪些內(nèi)容
⑥:將格式器添加到處理器:處理器將使用此格式器格式化日志
⑦:將處理器添加到記錄器:記錄器將使用此處理器處理日志
如果希望日志保存到文件中,只需重新創(chuàng)建一個處理器,將其添加到記錄器中即可
# 創(chuàng)建控制器,將日志寫入到文件中 ch_file = logging.FileHandler('aa.log') ch_file.setLevel(logging.DEBUG) # 為處理器設(shè)置格式器 ch_file.setFormatter(formatter) # 將處理器添加到記錄器 logger.addHandler(ch_file)
3.8.2 配置字典
Python 3.2中引入的一種新的配置日志記錄的方法–用字典來保存logging配置信息。這相對于上面所講的基于配置文件來保存logging配置信息的方式來說,功能更加強大,也更加靈活,因為我們可把很多的數(shù)據(jù)轉(zhuǎn)換成字典。比如,我們可以使用JSON格式的配置文件、YAML格式的配置文件,然后將它們填充到一個配置字典中;或者,我們也可以用Python代碼構(gòu)建這個配置字典,或者通過socket接收pickled序列化后的配置信息。總之,你可以使用你的應(yīng)用程序可以操作的任何方法來構(gòu)建這個配置字典
編寫配置字典,然后通過 logging.config.dictConfig
方法調(diào)用此字典
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')
①:創(chuàng)建了一個名為 simple 的格式器
②:創(chuàng)建了一個名為 console 的處理器,并設(shè)置處理器使用的格式器為 simple
③:創(chuàng)建了額一個名為 simple 的記錄器,并設(shè)置記錄器使用的處理器為 console
2、增加新的格式器、處理器和記錄器
創(chuàng)建一個新的格式器
standard = '%(levelname)s:%(asctime)s:%(filename)s:%(lineno)d:%(message)s'
添加
創(chuàng)建新的處理器,用于將日志寫入文件
在記錄器中添加此處理器
運行程序,日志將同時打印到控制臺和日志文件中
這里應(yīng)該體會到了使用配置字典的好處
創(chuàng)建記錄器時,選擇 standard
,則只會輸出 ERROR 以上的日志信息
3、配置文件-yaml
開發(fā)時,最好的方式,當然不是在程序中編寫代碼做出上面配置
而是,新建配置文件,程序運行時,讀取配置文件
我們將配置寫到一個 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
視圖函數(shù)代碼,讀取 yaml 文件,并將其轉(zhuǎn)換成 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 } } }
視圖函數(shù)
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. django 日志
上面介紹了 Python 中使用日志的方式,有了這些基礎(chǔ)之后,學習 django 中日志的使用就事半功倍了
django 中仍然使用了 logging
模塊做日志處理
其實,3.8 節(jié)已經(jīng)講完了,就是這么用。。。。
附:關(guān)于 logging 模塊的詳細說明
在Python的logging模塊中,主要包含下面四大方面:
- Loggers: 記錄器
- Handlers:處理器
- Filters: 過濾器
- Formatters: 格式化器
下文詳細說明一下這四大模塊
4.1 Loggers
logger 是日志系統(tǒng)的入口。每個 logger 都是命名了的 bucket, 消息寫入 bucket 以便進一步處理。
logger 可以配置日志級別。日志級別描述了由該 logger 處理的消息的嚴重性。Python 定義了下面幾種日志級別:
DEBUG
:排查故障時使用的低級別系統(tǒng)信息;INFO
:一般的系統(tǒng)信息;WARNING
:描述系統(tǒng)發(fā)生了一些小問題的信息;ERROR
:描述系統(tǒng)發(fā)生了大問題的信息;CRITICAL
:描述系統(tǒng)發(fā)生嚴重問題的信息;
每一條寫入 logger 的消息都是一條日志記錄。每一條日志記錄也包含日志級別,代表對應(yīng)消息的嚴重程度。日志記錄還包含有用的元數(shù)據(jù),來描述被記錄的事件細節(jié),例如堆棧跟蹤或者錯誤碼。
當logger處理一條消息時,會將自己的日志級別和這條消息的日志級別做對比。如果消息的日志級別匹配或者高于 logger 的日志級別,它就會被進一步處理。否則這條消息就會被忽略掉。
當 logger 確定了一條消息需要處理之后,會把它傳給Handler。
4.2 Handlers
Handler是決定如何處理logger中每一條消息的引擎。它描述特定的日志行為,比如把消息輸出到屏幕、文件或網(wǎng)絡(luò) socket。
和logger一樣,handler也有日志級別的概念。如果一條日志記錄的級別不匹配或者低于handler的日志級別,對應(yīng)的消息會被 handler忽略。
一個logger可以有多個handler,每一個handler可以有不同的日志級別。這樣就可以根據(jù)消息的重要性不同,來提供不同格式的輸出。例如,你可以添加一個 handler 把ERROR和CRITICAL消息發(fā)到尋呼機,再添加另一個handler把所有的消息(包括 ERROR和CRITICAL消息)保存到文件里以便日后分析。
4.3 過濾器
在日志從 logger 傳到 handler 的過程中,使用 Filter 來做額外的控制。
默認情況下,只要級別匹配,任何日志消息都會被處理。不過,也可以通過添加filter來給日志處理的過程增加額外條件。例如,可以添加一個filter只允許某個特定來源的ERROR消息輸出。
Filter還被用來在日志輸出之前對日志記錄做修改。例如,可以寫一個filter,當滿足一定條件時,把日志記錄從ERROR降到 WARNING級別。
Filter在logger和handler中都可以添加;多個filter可以鏈接起來使用,來做多重過濾操作。
4.4 Formatters
日志記錄最終是需要以文本來呈現(xiàn)的。Formatter 描述了文本的格式。一個 formatter 通常由包含 LogRecord attributes 的 Python 格式化字符串組成,不過你也可以為特定的格式來配置自定義的 formatter。
到此這篇關(guān)于django 中使用日志的文章就介紹到這了,更多相關(guān)django 使用日志內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
PyCharm GUI界面開發(fā)和exe文件生成的實現(xiàn)
這篇文章主要介紹了PyCharm GUI界面開發(fā)和exe文件生成,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-03-03用Python調(diào)用win命令行提高工作效率的實例
今天小編就為大家分享一篇用Python調(diào)用win命令行提高工作效率的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-08-08python不到50行代碼完成了多張excel合并的實現(xiàn)示例
這篇文章主要介紹了python不到50行代碼完成了多張excel合并的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-05-05Python如何實現(xiàn)轉(zhuǎn)換URL詳解
這篇文章主要介紹了Python如何實現(xiàn)轉(zhuǎn)換URL詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-07-07Python辦公自動化從Excel中計算整理數(shù)據(jù)并寫入Word
這篇文章主要為大家介紹了Python辦公自動化從Excel中計算整理數(shù)據(jù)并寫入Word示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06