乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      python logging

       londonKu 2012-11-23

      開發(fā)Python, 一直以來都是使用自己編寫的logging模塊. 比較土......

      今天發(fā)現(xiàn)python的標準模塊的這個功能做的挺好, 記錄一下, 以后使用模塊來進行l(wèi)ogging.

      對于這個模塊的介紹網(wǎng)上也很多, 我也不用自己寫了, 比較好的如下,

      http://crazier9527./blog/290018    Python的標準logging模塊

      http://blog./2010/06/03/python-logging-module/   Python的logging模塊

      http://docs./library/logging.html  官方文檔

      下面就對于在項目中比較需要用到的部分摘錄一些,

      簡單的例子

      [python] view plaincopy
      1. import logging  
      2. import sys  
      3. logger = logging.getLogger("endlesscode")  
      4. formatter = logging.Formatter('%(name)-12s %(asctime)s %(levelname)-8s %(message)s''%a, %d %b %Y %H:%M:%S',)  
      5. file_handler = logging.FileHandler("test.log")  
      6. file_handler.setFormatter(formatter)  
      7. stream_handler = logging.StreamHandler(sys.stderr)  
      8. logger.addHandler(file_handler)  
      9. logger.addHandler(stream_handler)  
      10. #logger.setLevel(logging.ERROR)  
      11. logger.error("fuckgfw")  
      12. logger.removeHandler(stream_handler)  
      13. logger.error("fuckgov")  

      上面這段代碼基本包含logging模塊的基本feature

      GetLogger

      GetLogger() returns a reference to a logger instance with the specified name if it is provided, or root if not. The names are period-separated hierarchical structures. Multiple calls to getLogger() with the same name will return a reference to the same logger object.
      后面會看到這種以'.'分隔的hierarchical structures有什么用.

      Formatter

      Formatter對象定義了最終log信息的順序,結構和內容, 后面會詳細解釋.

      Handler

      這兒用到了StreamHandler和FileHandler, 用于向不同的輸出端打log.

      SetLevel

      Logging有如下級別: DEBUG,INFO,WARNING,ERROR,CRITICAL

      默認級別是WARNING, logging模塊只會輸出指定level以上的log

      這樣的好處, 就是在項目開發(fā)時debug用的log, 在產(chǎn)品release階段不用一一注釋, 只需要調整logger的級別就可以了, 很方便的.

       

      Formatter

      Formatter對象定義了最終log信息的順序,結構和內容.于基本的logging.Handler類不同,應用可以直接實例化formatter類,當然,如果需要你也可以子例化formatter以便定制它的一些行為.構造函數(shù)接受兩個可選參數(shù):一個信息格式字符串和一個日期格式字符串.如果沒有信息格式字符串,直接輸出log信息.如果沒有日期格式字符串,默認的格式是:%Y-%m-%d %H:%M:%S

      上面的代碼給出了Formatter的例子, 下面表格給出所有可以使用的format,

       

      Handler

      Logging包含很多handler, 可能用到的有下面幾種

      1. StreamHandler instances send error messages to streams (file-like objects).
      2. FileHandler instances send error messages to disk files.
      3. RotatingFileHandler instances send error messages to disk files, with support for maximum log file sizes and log file rotation.
      4. TimedRotatingFileHandler instances send error messages to disk files, rotating the log file at certain timed intervals.
      5. SocketHandler instances send error messages to TCP/IP sockets.
      6. DatagramHandler instances send error messages to UDP sockets.
      7. SMTPHandler instances send error messages to a designated email address.

      最常用的也就是StreamHandler和FileHandler

       

      Configuration

      1. Creating loggers, handlers, and formatters explicitly using Python code that calls the configuration methods listed above.
      2. Creating a logging config file and reading it using the fileConfig() function.
      3. Creating a dictionary of configuration information and passing it to the dictConfig() function.

      第一種配置方法前面的code里面已經(jīng)有了

      第二種配置方法, 我覺得在項目里面是比較實用的, 通過編寫配置文件, 在code里面只需要用fileConfig配置一下logging, 顯得比較簡潔.

      這個可以參照http://crazier9527./blog/290026 或 官方文檔.

       

      Multiple handlers and formatters

      Loggers是一個簡單的Python對象.addHandler()方法沒有最多或者最少配額,當你的應用需要在把所有的log信息打到一個txt文件中去,同時又需要把errors級別一上的錯誤信息打到console時,你就會體會到這個特性的好處.只要簡單的配置一下合適的handlers就可以實現(xiàn)這個功能.應用對logging的調用用不著修改.以下是對前一個基于module的配置例子的改進:

      [python] view plaincopy
      1. import logging  
      2. logger = logging.getLogger("simple_example")  
      3. logger.setLevel(logging.DEBUG)  
      4. # create file handler which logs even debug messages  
      5. fh = logging.FileHandler("spam.log")  
      6. fh.setLevel(logging.DEBUG)  
      7. # create console handler with a higher log level  
      8. ch = logging.StreamHandler()  
      9. ch.setLevel(logging.ERROR)  
      10. # create formatter and add it to the handlers  
      11. formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")  
      12. ch.setFormatter(formatter)  
      13. fh.setFormatter(formatter)  
      14. # add the handlers to logger  
      15. logger.addHandler(ch)  
      16. logger.addHandler(fh)  
      17. # "application" code  
      18. logger.debug("debug message")  
      19. logger.info("info message")  
      20. logger.warn("warn message")  
      21. logger.error("error message")  
      22. logger.critical("critical message")  

       

      多module使用Logging(只要在同一個Python interpreter process)

      上面我曾提到過,所有的對logging.getLogger(‘someLogger’)的調用都會返回同一個對象.這個規(guī)則不僅僅在同一個module有效,而且對在同一個Python的解釋器進程里面的多個module也有效.而且,應用代碼可以在一個module里面定義一個父logger,而在另一個module里面繼承這個logger,所有對這個子logger的調用都會轉到父logger里面去,如下所示:

      下面這個是主模塊的代碼,

      [python] view plaincopy
      1. import logging  
      2. import auxiliary_module  
      3. # create logger with "spam_application"  
      4. logger = logging.getLogger("spam_application")  
      5. logger.setLevel(logging.DEBUG)  
      6. # create file handler which logs even debug messages  
      7. fh = logging.FileHandler("spam.log")  
      8. fh.setLevel(logging.DEBUG)  
      9. # create console handler with a higher log level  
      10. ch = logging.StreamHandler()  
      11. ch.setLevel(logging.ERROR)  
      12. # create formatter and add it to the handlers  
      13. formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")  
      14. fh.setFormatter(formatter)  
      15. ch.setFormatter(formatter)  
      16. # add the handlers to the logger  
      17. logger.addHandler(fh)  
      18. logger.addHandler(ch)  
      19. logger.info("creating an instance of auxiliary_module.Auxiliary")  
      20. a = auxiliary_module.Auxiliary()  
      21. logger.info("created an instance of auxiliary_module.Auxiliary")  
      22. logger.info("calling auxiliary_module.Auxiliary.do_something")  
      23. a.do_something()  
      24. logger.info("finished auxiliary_module.Auxiliary.do_something")  
      25. logger.info("calling auxiliary_module.some_function()")  
      26. auxiliary_module.some_function()  
      27. logger.info("done with auxiliary_module.some_function()")  

      這個是子模塊的代碼,

      [python] view plaincopy
      1. import logging  
      2. # create logger  
      3. module_logger = logging.getLogger("spam_application.auxiliary")  
      4. class Auxiliary:  
      5.     def __init__(self):  
      6.         self.logger = logging.getLogger("spam_application.auxiliary.Auxiliary")  
      7.         self.logger.info("creating an instance of Auxiliary")  
      8.     def do_something(self):  
      9.         self.logger.info("doing something")  
      10.         a = 1 + 1  
      11.         self.logger.info("done doing something")  
      12. def some_function():  
      13.     module_logger.info("received a call to /"some_function/"")  

      可以看到, 我們在主模塊里面定義了一個logger 'spam_application', 并對他進行了配置.

      那么在這個解釋器進程里面的任何地方去通過getLogger('spam_application')得到的對象都是一樣的, 不需要從新定義配置, 可以直接使用.

      更方便的是, 你定義任意該logger的子logger, 都可以共享父logger的定義和配置

      所謂的父子logger只是簡單的通過命名來識別, 任意以'spam_application.'開頭的logger都是他的子logger, 例如'spam_application.auxiliary'

      這個在實際的開發(fā)中, 還是很方便的, 對于一個application,

      首先通過logging配置文件編寫好這個application所對應的log策略, 可以只生成一個根logger, 比如叫'Project'

      然后在Main函數(shù)里面, 通過fileConfig加載logging的配置

      接著在appliction的任意地方, 不同的模塊中, 可以使用Project的子logger, 如Project.UI, Project.Core, 來進行l(wèi)og, 并且不需要反復的定義和配置各個logger.





      如果使用Python寫一個比較大型的程序,你一定會用上日志系統(tǒng)。特別是Python這樣的動態(tài)語言,很多錯誤都只能在運行的時候才能發(fā)現(xiàn),一個 好的日志系統(tǒng)對于Python程序相當重要。最簡單的解決方案當然是直接使用print輸出運行信息。但是這樣太簡單了,沒有分級功能,如果在發(fā)布的時候 想去掉調試用的運行信息還得找出所有的print語句進行修改。再者,print只能輸出到控制臺,想要輸出到文件或者通過電子郵件發(fā)送到其他地方,一個 print語句就沒辦法解決了。


      通過使用Python的日志系統(tǒng),就可以解決以上問題。

      首先看一下這個示例:
      import logging
      LOG=logging.getLogger(’應用程序名’)
      console = logging.StreamHandler()
      console.setLevel(logging.INFO)
      LOG.addHandler(console)
      LOG.debug(’調試信息’)
      LOG.info(’有用的信息’)
      LOG.warning(’警告信息’)
      LOG.error(’錯誤信息’)
      LOG.critical(’嚴重錯誤信息’)
      上面的代碼想控制臺輸出了五種錯誤信息。分為五個從低到高的級別,從DEBUG到CRITICAL。此外,我們還指定了程序輸出的級別,只有INFO級別以上的信息才會被輸出。


      這就是日志系統(tǒng)最常用的使用方法。這段代碼中有兩個概念可以幫助我們更進一步使用Python的日志系統(tǒng):


      1.        “Logger”。每個程序在輸出信息之前都要獲得一個Logger。Logger通常對應了程序的模塊名,比如聊天工具的圖形界面模塊可以這樣獲得它的Logger:
      LOG=logging.getLogger(”chat.gui”)
      而核心模塊可以這樣:
      LOG=logging.getLogger(”chat.kernel”)

      我們接下來可以看到使用這種命名方法的用途。

      2.        “Handler”。用于處理程序的輸出。 Python的日志系統(tǒng)有多種Handler可以使用。有些Handler可以把信息輸出到控制臺,有些Logger可以把信息輸出到文件,還有些 Handler可以把信息發(fā)送到網(wǎng)絡上。如果覺得不夠用,還可以編寫自己的Handler。
      所有的Handler可以支持三個操作:

      1.      設置輸出格式。比如設置輸出的信息中包含時間和級別信息:
      LOG=logging.getLogger(”chat.gui”)
      console = logging.StreamHandler()
      console.setLevel(logging.INFO)
      formatter = logging.Formatter(’%(asctime)s %(levelname)s %(message)s’)
      console.setFormatter(formatter)
      LOG.addHandler(console)
      熟悉Python的朋友應該會發(fā)現(xiàn),logging.Formatter的參數(shù)實際上只是Python常用的“%”字符串格式化。它使用“%(name)s”表示占位符。下面是一個完整的表格,展示了日志系統(tǒng)可以輸出的各種信息:


      %(name)s                           Logger的名字

      %(levelno)s                        數(shù)字形式的日志級別

      %(levelname)s                  文本形式的日志級別

      %(pathname)s                  調用日志輸出函數(shù)的模塊的完整路徑名,可能沒有

      %(filename)s                     調用日志輸出函數(shù)的模塊的文件名

      %(module)s                       調用日志輸出函數(shù)的模塊名

      %(funcName)s                  調用日志輸出函數(shù)的函數(shù)名

      %(lineno)d                          調用日志輸出函數(shù)的語句所在的代碼行

      %(created)f                         當前時間,用UNIX標準的表示時間的浮點數(shù)表示

      %(relativeCreated)d          輸出日志信息時的,自Logger創(chuàng)建以來的毫秒數(shù)

      %(asctime)s                       字符串形式的當前時間。默認格式是“2003-07-08 16:49:45,896”。逗號后面的是毫秒

      %(thread)d                          線程ID。可能沒有

      %(threadName)s               線程名。可能沒有

      %(process)d                       進程ID??赡軟]有

      %(message)s                    用戶輸出的消息


      2.      設置輸出級別
      在上面我們已經(jīng)演示了如何設置輸出級別了。除了Python內置的五種級別,我們還可以自定義輸出級別。
      TODO 子定義輸出級別

      3.      設置過濾器
      細心的朋友一定會發(fā)現(xiàn)前文調用logging.getLogger()時參數(shù)的格式類似于“A.B.C”。采取這樣的格式其實就是為了可以配置過濾器??匆幌逻@段代碼:
      LOG=logging.getLogger(”chat.gui.statistic”)
      console = logging.StreamHandler()
      console.setLevel(logging.INFO)
      formatter = logging.Formatter(’%(asctime)s %(levelname)s %(message)s’)
      console.setFormatter(formatter)
      filter=logging.Filter(”chat.gui”)
      console.addFilter(filter)
      LOG.addHandler(console)

      和前面不同的是我們在Handler上添加了一個過濾器。現(xiàn)在我們輸出日志信息的時候就會經(jīng)過過濾器的處理。名為“A.B”的過濾器只讓名字帶有 “A.B”前綴的Logger輸出信息。可以添加多個過濾器,只要有一個過濾器拒絕,日志信息就不會被輸出。另外,在Logger中也可以添加過濾器。

      每個Logger可以附加多個Handler。接下來我們就來介紹一些常用的Handler:
      1)        logging.StreamHandler
      使用這個Handler可以向類似與sys.stdout或者sys.stderr的任何文件對象(file object)輸出信息。它的構造函數(shù)是:
      StreamHandler([strm])
      其中strm參數(shù)是一個文件對象。默認是sys.stderr

      2)    2.logging.FileHandler
      和StreamHandler類似,用于向一個文件輸出日志信息。不過FileHandler會幫你打開這個文件。它的構造函數(shù)是:
      FileHandler(filename[,mode])
      filename是文件名,必須指定一個文件名
      mode是文件的打開方式。參見Python內置函數(shù)open()的用法。默認是’a',即添加到文件末尾。

      3)    3.logging.handlers.RotatingFileHandler
      這個Handler類似于上面的FileHandler,但是它可以管理文件大小。當文件達到一定大小之后,它會自動將當前日志文件改名,然后創(chuàng)建 一個新的同名日志文件繼續(xù)輸出。比如日志文件是chat.log。當chat.log達到指定的大小之后,RotatingFileHandler自動把 文件改名為chat.log.1。不過,如果chat.log.1已經(jīng)存在,會先把chat.log.1重命名為chat.log.2。。。最后重新創(chuàng)建 chat.log,繼續(xù)輸出日志信息。它的構造函數(shù)是:
      RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
      其中filename和mode兩個參數(shù)和FileHandler一樣。
      maxBytes用于指定日志文件的最大文件大小。如果maxBytes為0,意味著日志文件可以無限大,這時上面描述的重命名過程就不會發(fā)生。
      backupCount用于指定保留的備份文件的個數(shù)。比如,如果指定為2,當上面描述的重命名過程發(fā)生時,原有的chat.log.2并不會被更名,而是被刪除。

      4)    4.logging.handlers.TimedRotatingFileHandler
      這個Handler和RotatingFileHandler類似,不過,它沒有通過判斷文件大小來決定何時重新創(chuàng)建日志文件,而是間隔一定時間就 自動創(chuàng)建新的日志文件。重命名的過程與RotatingFileHandler類似,不過新的文件不是附加數(shù)字,而是當前時間。它的構造函數(shù)是:
      TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
      其中filename參數(shù)和backupCount參數(shù)和RotatingFileHandler具有相同的意義。
      interval是時間間隔。
      when參數(shù)是一個字符串。表示時間間隔的單位,不區(qū)分大小寫。它有以下取值:
      S 秒M 分H 小時D 天W 每星期(interval==0時代表星期一)midnight 每天凌晨

      5)    5.logging.handlers.SocketHandler
      6)    6.logging.handlers.DatagramHandler
      以上兩個Handler類似,都是將日志信息發(fā)送到網(wǎng)絡。不同的是前者使用TCP協(xié)議,后者使用UDP協(xié)議。它們的構造函數(shù)是:
      Handler(host, port)
      其中host是主機名,port是端口名

      7)    7.logging.handlers.SysLogHandler
      8)    8.logging.handlers.NTEventLogHandler
      9)    9.logging.handlers.SMTPHandler
      10)    10.logging.handlers.MemoryHandler
      11)    11.logging.handlers.HTTPHandler

      這些我自己沒用過,期待大家補充?;蛘邊⒖糚ython的使用手冊

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多