日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

keil debug如何在watch直接修改变量值_python日志记录系列教程,内置logging模块(一),直接使用logging模块的基础日志记录

發布時間:2024/7/23 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 keil debug如何在watch直接修改变量值_python日志记录系列教程,内置logging模块(一),直接使用logging模块的基础日志记录 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:成熟的軟件開發不可避免的要進行日志記錄,python內置模塊logging提供了強大的日志記錄能力,本文將從多個角度,由淺入深的介紹logging的常見使用方法和一些基本概念,本此系列文章分為兩篇,本文為系列文章第一篇,介紹實用logging模塊進行基本的日志記錄操作。本文主要都是直接使用 logging.xxxx() 的方式,這是最簡單初步的日志記錄,不涉及任何復雜的類和對象,這些將會在下一篇文章中來說明。

一、什么是日志記錄

所謂的日志記錄就是對軟件執行時所發生事件的一種追蹤方式。軟件開發人員對他們的代碼添加日志調用,借此來指示某事件的發生。一個事件通過一些包含變量數據的描述信息來描述(比如:每個事件發生時的數據都是不同的)。開發者還會區分事件的重要性,重要性也被稱為 等級 或 嚴重性

1.1 什么時候使用 Logging

對于簡單的日志使用來說日志功能提供了一系列便利的函數。它們是 debug(),info(),warning(),error() 和 critical()。想要決定何時使用日志,請看下表,其中顯示了對于每個通用任務集合來說最好的工具。

你想要執行的任務此任務最好的工具
對于命令行或程序的應用,結果顯示在控制臺。print(),這是我們自己常用的,顯示某一些信息,直接打印結果,但是比較低級
在對程序的普通操作發生時提交事件報告(比如:狀態監控和錯誤調查)http://logging.info() 函數(當有診斷目的需要詳細輸出信息時使用 logging.debug() 函數)
提出一個警告信息基于一個特殊的運行時事件warnings.warn() 位于代碼庫中,該事件是可以避免的,需要修改客戶端應用以消除告警
logging.warning() 不需要修改客戶端應用,但是該事件還是需要引起關注
對一個特殊的運行時事件報告錯誤引發異常
報告錯誤而不引發異常(如在長時間運行中的服務端進程的錯誤處理)logging.error(), logging.exception() 或 logging.critical() 分別適用于特定的錯誤及應用領域

1.2 日志記錄的5個等級

日志功能應以所追蹤事件級別或嚴重性而定。各級別適用性如下(以嚴重程度遞增):

級別何時使用
DEBUG細節信息,僅當診斷問題時適用。
INFO確認程序按預期運行,但是要提示一些相關的信息,
WARNING表明有已經或即將發生的意外(例如:磁盤空間不足)。程序仍按預期進行,但是會有警告,可能出現什么錯誤。
ERROR由于嚴重的問題,程序的某些功能已經不能正常執行
CRITICAL嚴重的錯誤,表明程序已不能繼續執行

以及嚴重程度排序為:

debug<info<warning<error<critical

默認的級別是``WARNING``,意味著只會追蹤該級別以及該級別以上的事件,當然我們可以更改日志配置,重新設置默認值。

另外,我們需要查看所記錄的日志,一般日志輸出會有兩種形式,

所追蹤事件可以以不同形式處理。最簡單的方式是輸出到控制臺。另一種常用的方式是寫入磁盤文件。默認情況下,日志輸出信息會顯示在控制臺上。下面也會以這兩種方式來加以說明。

1.3 logging模塊初識

二、logging模塊的常規基礎操作

2.1 logging日志記錄的基本配置

函數原型如下:

該函數支持以下關鍵字參數。

格式描述
filename使用指定的文件名而不是 StreamHandler 創建 FileHandler。在需要將日志寫入到日志文件的時候使用
filemode日志文件的寫入模式.,默認的是"a",默認是追加的方式,若要每一次都重新寫入,則使用"w"
format使用的指定格式字符串。
datefmt時間格式的字符串
styleIf format is specified, use this style for the format string. One of '%', '{' or '$' for printf-style, str.format() or string.Template respectively. Defaults to '%'.
字符串的格式化方式的選擇,參考下面的style參數詳解。
level設置根記錄器級別去指定 level.默認的是warning,可以重新指定,比如http://logging.INFO logging.DEBUG 等等,
streamUse the specified stream to initialize the StreamHandler. Note that this argument is incompatible with filename - if both are present, a ValueError is raised.(后面用到了再說)
handlersIf specified, this should be an iterable of already created handlers to add to the root logger. Any handlers which don't already have a formatter set will be assigned the default formatter created in this function. Note that this argument is incompatible with filename or stream - if both are present, a ValueError is raised.(后面用到了再說)

對basicConfig的調用應該在 debug、info等函數的前面。因為它被設計為一次性的配置,只有第一次調用會進行操作,隨后的調用不會產生有效操作。

2.2 將日志寫入文件

2.3 多個模塊中使用日志記錄

如果你的程序包含多個模塊,這里有一個如何組織日志記錄的示例:

如果你運行 myapp.py ,你應該在 myapp.log 中看到:

我們發現,不同模塊中所記錄的日志信息都被保存到了同一個日志文件里面了。

2.4 格式化輸出以及記錄相關的變量值到日志文件

前面有文章專門介紹了python中的字符串格式化的幾種方法,包括使用百分號%、str.format、string.Template模板等方法,可以參考前面的文章:

python字符串格式化深入詳解(四種方法)

所以,要定義自己的字符串輸出格式,要記錄相關的變量到字符串中,我們可以這樣做。

要記錄變量數據,請使用格式字符串作為事件描述消息,并將變量數據作為參數附加。 例如:

如你所見,

logging日志記錄的字符串格式化,將數據合并到字符串中所采用的方式是 百分號% 的形式,
但是如果我想要使用其他的字符串格式化的方法怎么辦呢?就需要通過指定style參數來決定了,style的取值可以是三個,即
  • '%':這是默認的,即默認使用百分號%格式的字符串格式化方法;
  • '{':表示使用str.format()的字符串格式化方法;
  • '$':表示使用string.Template的格式化方法;

為什么是默認使用百分號 % 格式化工具呢?主要是因為logging的出現時間比這兩種格式化方法要早一些,但是并不是說完全不支持,現在完全有其他的方法讓logging支持str.format()和string.Template()這些格式,只需要設置不同的style參數值即可。


三、logging模塊的格式化設置以及時間格式化

當我們看之前的記錄日志的時候,我們發現,記錄的日志總是下面的格式,如下:

即所謂的:

日志類別嚴重程度:root:message

這樣的格式,那么能不能進行更改呢?這個自然是可以的,怎么更改呢,如下:

3.1 消息顯示的格式設置——basicConfig的 format 參數

要更改用于顯示消息的格式,你需要指定要使用的格式:

這將輸出:

請注意,前面示例中出現的“root”已消失。

對于可以出現在格式字符串中的全部內容,你可以參考以下文檔 LogRecord 屬性 ,在后面的系列文章第二篇中,還會深入探討日志記錄的高級主題,來說明的。

下面是常見的格式設置的字段標識:

  • %(asctime)s:日志創建時的普通時間;
  • %(created)f:日志創建時的時間(由time.time()返回);
  • %(filename)s:文件名;
  • %(funcName)s:調用日志記錄的函數;
  • %(levelname)s:日志消息的文本級別;
  • %(levelno)s:日志消息的數字級別;
  • %(lineno)d:調用日志消息的行號;
  • %(msecs)d:創建時間的毫秒部分;
  • %(message)s:日志消息;
  • %(name)s:日志器的名稱;
  • %(pathname)s:記錄日志的源文件的路徑名;
  • %(process)d:進程ID;
  • %(processName)s:進程名;
  • %(thread)d:線程ID;
  • %(threadName)s:線程名;
  • %(relativeCreated)d:創建日志記錄的時間(以毫秒為單位)

借助于這些格式,我們可以自定義日志記錄,比如顯示時間:

這樣,日志中除了記錄消息等級、消息信息外,還會記錄上消息創建的時間。

3.2 設置日志記錄的時間顯示的格式——basicConfig的datefmt參數

那我們可不可以更改時間顯示的格式呢?這個自然是能的,

日期/時間顯示的默認格式(如上所示)類似于 ISO8601 或 RFC 3339 。 如果你需要更多地控制日期/時間的格式,請為 basicConfig 提供 datefmt 參數,

需要格外注意的是:datefmt 參數的格式與 time.strftime() 支持的格式相同。

如下例所示:

那到底有哪一些格式呢?可以參考官網:https://docs.python.org/zh-cn/3.7/library/time.html#time.strftime

函數原型為:

轉換一個元組或 struct_time 表示的由 gmtime() 或 localtime() 返回的時間到由 format 參數指定的字符串。如果未提供 t ,則使用由 localtime() 返回的當前時間。 format 必須是一個字符串。如果 t 中的任何字段超出允許范圍,則引發 ValueError 。

0是時間元組中任何位置的合法參數;如果它通常是非法的,則該值被強制改為正確的值。

以下指令可以嵌入 format 字符串中。它們顯示時沒有可選的字段寬度和精度規范,并被 strftime() 結果中的指示字符替換:

指令含義注釋
%a本地化的縮寫星期中每日的名稱。
%A本地化的星期中每日的完整名稱。
%b本地化的月縮寫名稱。
%B本地化的月完整名稱。
%c本地化的適當日期和時間表示。
%d十進制數 [01,31] 表示的月中日。
%H十進制數 [00,23] 表示的小時(24小時制)。
%I十進制數 [01,12] 表示的小時(12小時制)。
%j十進制數 [001,366] 表示的年中日。
%m十進制數 [01,12] 表示的月。
%M十進制數 [00,59] 表示的分鐘。
%p本地化的 AM 或 PM 。(1)
%S十進制數 [00,61] 表示的秒。(2)
%U十進制數 [00,53] 表示的一年中的周數(星期日作為一周的第一天)作為。在第一個星期日之前的新年中的所有日子都被認為是在第0周。(3)
%w十進制數 [0(星期日),6] 表示的周中日。
%W十進制數 [00,53] 表示的一年中的周數(星期一作為一周的第一天)作為。在第一個星期一之前的新年中的所有日子被認為是在第0周。(3)
%x本地化的適當日期表示。
%X本地化的適當時間表示。
%y十進制數 [00,99] 表示的沒有世紀的年份。
%Y十進制數表示的帶世紀的年份。
%z時區偏移以格式 +HHMM 或 -HHMM 形式的 UTC/GMT 的正或負時差指示,其中H表示十進制小時數字,M表示小數分鐘數字 [-23:59, +23:59] 。
%Z時區名稱(如果不存在時區,則不包含字符)。
%%字面的 '%' 字符。

注釋:

  • 當與 strptime() 函數一起使用時,如果使用 %I 指令來解析小時, %p 指令只影響輸出小時字段。
  • 范圍真的是 0 到 61 ;值 60 在表示 leap seconds 的時間戳中有效,并且由于歷史原因支持值 61 。
  • 當與 strptime() 函數一起使用時, %U 和 %W 僅用于指定星期幾和年份的計算。
  • 下面是一個示例,一個與 RFC 2822 Internet電子郵件標準以兼容的日期格式。

    個人總結:

    個人習慣使用的格式為,年月日,時分秒,星期數,如下:

    四、日志記錄的堆棧追蹤

    前面都是一些最簡單的日志記錄操作與格式設置,但是我們在編寫python代碼的時候,往往涉及到多個函數之間的調用,我們需要跟蹤函數調用的堆棧信息,這樣才能定位到到底是哪一個函數的哪一個位置出現了錯誤,這才更加合理。

    再次回顧日志記錄實際上是做一件什么事?

    • 即當滿足什么條件的時候、或者是當某一件事情發生的時候,開始記錄日志,明白這思想很重要
    • 現在我們要做的就是,在程序執行出發了異常的時候,就開始記錄日志,并且記錄程序的堆棧信息,思想是相通的,只不過條件現在變成了,在異常發生的時候。

    首先其實我們發現,http://logging.xxx()的幾個函數(info、debug、warning、error、critical)他們的參數格式是一樣的,以error為例:

    有兩個非常關鍵的參數,它們是

    • stack_info:
    • exc_info:

    下面將分別來說明這兩個參數各自的作用

    (1)exc_info=True——出現異常時記錄堆棧調用信息

    先從一個簡單的函數調用例子來看

    有一個math_func.py模塊,實現了兩個函數,如下:

    然后有一個operation_func.py模塊,再進一步對這兩個函數進行包裝,以便進行選擇性的調用哪一個函數,如下:

    最后再主模塊main.py里面進行調用,如下:

    運行之后,打開日志文件,得到如下的結果

    從上面我們發現,錯誤信息以及堆棧信息全部清楚地記錄在了里面。這對于程序調試是至關重要的。

    以上就是出現錯誤的時候logging堆棧追蹤的全部實現,一般的調用模板如下:

    前面提到了由兩個參數,那么這兩個參數到底有什么區別呢?現總結如下:

    • exe_info參數:在搜索異常處理程序時,跟蹤異常而打開的堆棧幀的信息,這個是專門針對異常發生的時候記錄日志的;
    • stack_info參數:默認為 False。如果為 True,則將堆棧信息添加到日志消息中,包括實際的日志調用。請注意,這與通過指定 exc_info 顯示的堆棧信息不同:他主要是從堆棧底部到當前線程中的日志記錄調用的堆棧幀,什么意思呢?即使在未引發任何異常的情況下,也可以顯示如何到達代碼中的特定點。堆棧幀在標題行(即每一句日志記錄行)之后打印:
    • stack_info:簡單來說就是,根據每一個日志記錄語句所在的位置,打印出這一句日志記錄信息,并且在后面顯示這句日志記錄所在的函數堆棧的位置是在哪里。

    (2)stack_info=True——記錄每一句日志記錄語句所在代碼中的堆棧信息

    參考下面的例子:

    調用b函數,b中有調用a函數,得到下面的日志信息:

    從上面可以看出,stack_info它會詳細記錄每一條日志打印語句所在的位置,然后在日志信息后面加以顯示,這跟exe_info是有顯著區別的。

    (3)補充參數說明——extra參數的說明

    前面的3.1中在說明日志記錄的格式的時候,給出了很多預先定義好的格式,比如

    • %(asctime)s:日志創建時的普通時間;
    • %(created)f:日志創建時的時間(由time.time()返回);
    • %(filename)s:文件名;

    等等,有時候我們想定義自己的信息怎么辦呢?可以采用下面的方式,extra參數接受的參數是一個字典類型,如下例子所示:

    我們發現,自己定義的clientip、user、work都顯示了出來!

    實際上,上面的這種操作稱之為,向日志輸出中添加上下文信息

    除了傳遞給日志記錄函數的參數外,有時候我們還想在日志輸出中包含一些額外的上下文信息。比如,在一個網絡應用中,可能希望在日志中記錄客戶端的特定信息,如:遠程客戶端的IP地址和用戶名。這里我們來介紹以下幾種實現方式:

    • 通過向日志記錄函數傳遞一個extra參數引入上下文信息
    • 使用LoggerAdapters引入上下文信息
    • 使用Filters引入上下文信息

    具體說明請參考博文 《Python之向日志輸出中添加上下文信息》

    關于Python logging的更多高級用法,請參考文檔<< Logging CookBook >>。

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的keil debug如何在watch直接修改变量值_python日志记录系列教程,内置logging模块(一),直接使用logging模块的基础日志记录的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。