<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] ## 日志模塊四大組件 ### 組件功能 | 組件名稱 | 對應類名 | 功能描述 | | --- | --- | --- | | 日志器 | Logger | 提供了應用程序可一直使用的接口 | | 處理器 | Handler | 將logger創建的日志記錄發送到合適的目的輸出 | | 過濾器 | Filter | 提供了更細粒度的控制工具來決定輸出哪條日志記錄,丟棄哪條日志記錄 | | 格式器 | Formatter | 決定日志記錄的最終輸出格式 | ### 組件間關系: * 日志器(logger)需要通過處理器(handler)將日志信息輸出到目標位置,如:文件、sys.stdout、網絡等; * 不同的處理器(handler)可以將日志輸出到不同的位置; * 日志器(logger)可以設置多個處理器(handler)將同一條日志記錄輸出到不同的位置; * 每個處理器(handler)都可以設置自己的過濾器(filter)實現日志過濾,從而只保留感興趣的日志; * 每個處理器(handler)都可以設置自己的格式器(formatter)實現同一條日志以不同的格式輸出到不同的地方。 **總結:** 日志器(logger)是入口,真正干活兒的是處理器(handler),處理器(handler)還可以通過過濾器(filter)和格式器(formatter)對要輸出的日志內容做過濾和格式化等處理操作。 ![日志模塊間關系](https://www.github.com/noah-luo/imags/raw/master/year/1548481029754.png) ## 每個組件的主要功能 ### Logger組件 #### logger任務 Logger對象有3個任務要做: * 1)向應用程序代碼暴露幾個方法,使應用程序可以在運行時記錄日志消息; * 2)基于日志嚴重等級(默認的過濾設施)或filter對象來決定要對哪些日志進行后續處理; * 3)將日志消息傳送給所有感興趣的日志handlers。 > Logger對象最常用的方法分為兩類:配置方法 和 消息發送方法 #### 常用配置方法 | 方法 | 描述 | | --- | --- | | Logger.setLevel() | 設置日志器將會處理的日志消息的最低嚴重級別 | | Logger.addHandler() 和 Logger.removeHandler() | 為該logger對象添加 和 移除一個handler對象 | | Logger.addFilter() 和 Logger.removeFilter() | 為該logger對象添加 和 移除一個filter對象 | #### 常用消息發送方法 | 方法 | 描述 | | --- | --- | | Logger.debug(), Logger.info(), Logger.warning(), Logger.error(), Logger.critical() | 創建一個與它們的方法名對應等級的日志記錄 | | Logger.exception() | 創建一個類似于Logger.error()的日志消息 | | Logger.log() | 需要獲取一個明確的日志level參數來創建一個日志記錄 | > Logger.exception()與Logger.error()的區別在于:Logger.exception()將會輸出堆棧追蹤信息,另外通常只是在一個exception handler中調用該方法。 #### 獲取logger對象 一種方式是通過Logger類的實例化方法創建一個Logger類的實例,更通常的方法是用`logging.getLogger()`方法。 logging.getLogger()方法有一個可選參數name,該參數表示將要返回的日志器的名稱標識,如果不提供該參數,則其值為'root'。若以相同的name參數值多次調用getLogger()方法,將會返回指向同一個logger對象的引用。 * 聊天工具的圖形界面模塊可以這樣獲得它的Logger: ``` LOG=logging.getLogger(”chat.gui”)` ``` * 核心模塊可以這樣: ``` LOG=logging.getLogger(”chat.kernel”) ``` #### logger的層級結構與有效等級 * 層級結構 logger的名稱是一個以'.'分割的層級結構,每個'.'后面的logger都是'.'前面的logger的children * 有效等級(effective level) 如果一個logger上沒有被明確設置一個level,那么該logger就是使用它parent的level,直到找到個一個明確設置了level的祖先為止。root logger總是會有一個明確的level設置(默認為 WARNING)。當決定是否去處理一個已發生的事件時,logger的有效等級將會被用來決定是否將該事件傳遞給該logger的handlers進行處理。 * 繼承關系 child loggers在完成對日志消息的處理后,默認會將日志消息傳遞給與它們的祖先loggers相關的handlers。因此不必所有loggers定義和配置handlers,只需要為一個頂層的logger配置handlers,然后按照需要創建child loggers就可足夠了。可以通過將一個logger的propagate屬性設置為False來關閉這種傳遞機制。 ### **handler組件** #### Handler組件用途 Handler對象的作用是(基于日志消息的level)將消息分發到handler指定的位置(文件、網絡、郵件等)。Logger對象可以通過addHandler()方法為自己添加0個或者更多個handler對象。比如,一個應用程序可能想要實現以下幾個日志需求 * 1)把所有日志都發送到一個日志文件中; * 2)把所有嚴重級別大于等于error的日志發送到stdout(標準輸出); * 3)把所有嚴重級別為critical的日志發送到一個email郵件地址。 >這種場景就需要3個不同的handlers,每個handler負責發送一個特定級別的日志到一個特定的位置。 #### handler的配置方法 | 方法 | 描述 | | --- | --- | | Handler.setLevel() | 設置handler將會處理的日志消息的最低嚴重級別 | | Handler.setFormatter() | 為handler設置一個格式器對象 | | Handler.addFilter() 和 Handler.removeFilter() | 為handler添加 和 刪除一個過濾器對象 | >應用程序代碼不應該直接實例化和使用Handler實例。因為Handler是一個基類,它只定義了所有handlers都應該有的接口 #### 常用的Handler | Handler | 描述 | | --- | --- | | logging.StreamHandler | 將日志消息發送到輸出到Stream,如std.out, std.err或任何file-like對象。 | | logging.FileHandler | 將日志消息發送到磁盤文件,默認情況下文件大小會無限增長 | | logging.handlers.RotatingFileHandler | 將日志消息發送到磁盤文件,并支持日志文件按大小切割 | | logging.hanlders.TimedRotatingFileHandler | 將日志消息發送到磁盤文件,并支持日志文件按時間切割 | | logging.handlers.HTTPHandler | 將日志消息以GET或POST的方式發送給一個HTTP服務器 | | logging.handlers.SMTPHandler | 將日志消息發送給一個指定的email地址 | | logging.NullHandler | 該Handler實例會忽略error messages | #### RotatingFileHandler按大小切割 當文件達到一定大小之后,自動將當前日志文件改名,然后創建一個新的同名日志文件繼續輸出。 >比如日志文件是chat.log。當chat.log達到指定的大小之后,RotatingFileHandler自動把文件改名為chat.log.1。若chat.log.1已經存在,會先把chat.log.1重命名為chat.log.2。。。最后重新創建 chat.log,繼續輸出日志信息。 ``` RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]]) ``` * maxBytes用于指定日志文件的最大文件大小。如果maxBytes為0,意味著日志文件可以無限大,這時上面描述的重命名過程就不會發生。 * backupCount用于指定保留的備份文件的個數。比如,如果指定為2,當上面描述的重命名過程發生時,原有的chat.log.2并不會被更名,而是被刪除。 #### TimedRotatingFileHandler按時間切割 間隔一定時間就自動創建新的日志文件。重命名的過程與RotatingFileHandler類似,不過新的文件不是附加數字,而是當前時間。 ``` TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]]) ``` * `interval`是時間間隔。 * `when`參數是一個字符串。 表示時間間隔的單位,不區分大小寫。有以下取值: * S 秒 * M 分 * H 小時 * D 天 * W 每星期(interval==0時代表星期一) * midnight 每天凌晨 ### Formater組件 #### 用途和語法 日志的formatter是個獨立的組件,可以跟handler組合。Formater對象用于配置日志信息的最終順序、結構和內容。 Formatter類的構造方法定義如下: ``` logging.Formatter.__init__(fmt=None, datefmt=None, style='%') ``` * fmt:指定消息格式化字符串,如果不指定該參數則默認使用message的原始值 * datefmt:指定日期格式字符串,如果不指定該參數則默認使用"%Y-%m-%d %H:%M:%S" * style:可取值為 '%', '{'和 '$',如果不指定該參數則默認使用'%' #### 與handler組合舉例 ``` fh = logging.FileHandler("access.log") formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) #把formmater綁定到fh上 ``` ### Filter組件 #### 用途和語法 Filter可以被Handler和Logger用來做比level更細粒度的、更復雜的過濾功能。Filter是一個過濾器基類,它只允許某個logger層級下的日志事件通過過濾。該類定義如下: ``` class logging.Filter(name='A.B') filter(record) ``` >一個filter實例化時傳遞的name參數值為'A.B',那么該filter將只允許名稱為類似`'A.B','A.B,C','A.B.C.D','A.B.D'`的loggers產生的日志記錄通過過濾。如果name為空字符串,則允許所有的日志事件通過過濾。 filter方法用于具體控制傳遞的record記錄是否能通過過濾,如果該方法返回值為0表示不能通過過濾,返回值為非0表示可以通過過濾。 > 若需要,可以在filter(record)方法內部改變該record,比如添加、刪除或修改一些屬性。 > 還可以通過filter做一些統計工作,如計算一個特殊的logger或handler所處理的record數量等。 #### 自定義filter舉例 自定義一個filter對日志內容進行過濾 ``` class IgnoreBackupLogFilter(logging.Filter): """忽略帶db backup 的日志""" def filter(self, record): #固定寫法 return "db backup" not in record.getMessage() ``` > 注意filter函數會返加True or False,logger根據此值決定是否輸出此日志 然后把這個filter添加到logger中 ``` logger.addFilter(IgnoreBackupLogFilter()) ``` 下面的日志就會把符合filter條件的過濾掉 ``` logger.debug("test ....") logger.info("test info ....") logger.warning("start to run db backup job ....") logger.error("test error ....") ``` ## 完整案例 ### 同時輸出到屏幕和文件帶filter * 代碼 ```python import logging class IgnoreBackupLogFilter(logging.Filter): """忽略帶db backup 的日志""" def filter(self, record): #固定寫法 return "db backup" not in record.getMessage() # 1.定義兩個handler,分別輸出到標準流和文件 hand_c=logging.StreamHandler() hand_f=logging.FileHandler('mysql.log') hand_c.setLevel(logging.INFO) # 2.定義formatter并與handler綁定 format1=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') hand_c.setFormatter(format1) hand_f.setFormatter(format1) # 3.定義logger并設置日志級別 logg1=logging.getLogger('mysql') logg1.setLevel(logging.DEBUG) # 4.logger添加自定義的handler logg1.addHandler(hand_f) logg1.addHandler(hand_c) # 5.添加自定義的filter logg1.addFilter(IgnoreBackupLogFilter()) # 6.寫入日志 logg1.debug("1. test ....") logg1.info("2. test info ....") logg1.warning("3. start to run db backup job ....") logg1.error("4. test error ....") ``` * 輸出結果 ``` #屏幕輸出 2019-01-28 11:42:23,266 - mysql - INFO - 2. test info .... 2019-01-28 11:42:23,266 - mysql - ERROR - 4. test error .... #文件輸出 2019-01-28 11:42:23,266 - mysql - DEBUG - 1. test .... 2019-01-28 11:42:23,266 - mysql - INFO - 2. test info .... 2019-01-28 11:42:23,266 - mysql - ERROR - 4. test error .... # 解釋 logger中定義了日志級別,會向下基礎,所以文件中就用的logger定義的級別,而屏幕上的輸出由于還有handler定義的級別,導致第一條被過濾了掉了 ``` ### 文件自動截斷例子 ``` import logging logger = logging.getLogger(__name__) log_file = "timelog.log" fh = logging.handlers.TimedRotatingFileHandler(filename=log_file,when="S",interval=5,backupCount=3) formatter = logging.Formatter('%(asctime)s %(module)s:%(lineno)d %(message)s') fh.setFormatter(formatter) logger.addHandler(fh) logger.warning("test1") logger.warning("test12") logger.warning("test13") logger.warning("test14") ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看