2012-11-19 106 views
4

我使用logging模塊在我的應用程序上記錄消息。如何追溯記錄錯誤?

通常我來的情況下對一種格式的字符串或參數出錯會導致錯誤,例如:

import logging 
my_log = logging.getLogger("MyLog") 
# this is obviously wrong 
my_log.info('%d', "abc") 

結果是類似於下面的一個錯誤:

Traceback (most recent call last): 
    File "/usr/lib64/python2.6/logging/__init__.py", line 776, in emit 
    msg = self.format(record) 
    File "/usr/lib64/python2.6/logging/__init__.py", line 654, in format 
    return fmt.format(record) 
    File "/usr/lib64/python2.6/logging/__init__.py", line 436, in format 
    record.message = record.getMessage() 
    File "/usr/lib64/python2.6/logging/__init__.py", line 306, in getMessage 
    msg = msg % self.args 
TypeError: %d format: a number is required, not str 

但是,它只是顯示記錄模塊內的回溯;它不會告訴我在我的代碼中發生錯誤的位置。

有什麼辦法解決這個問題嗎?

+1

http://stackoverflow.com/questions/6898674/getting-a-more-useful-logging-module-error-output-in-python看起來像人誰也有類似的問題對你的;有一個代碼的答案用於繼承日誌記錄處理程序,以便在其中添加更好的堆棧跟蹤(包括您從中調用它的位置)。 – bouteillebleu

+0

我無法重現你的錯誤,但也許設置回溯限高的東西會有所幫助。 'import sys; sys.traceback_limit = 10'。 –

回答

3

我遇到了同樣的問題,找到錯誤的根源。日誌記錄模塊處理這種異常並且不停止程序 - 這對於日誌模塊來說是可接受的行爲。但是抑制異常並且在處理它時不提供足夠的信息。

我發現,現在用厚描述here

關鍵是要更換非常基本的記錄功能,做字符串格式化logging.LogRecord.getMessage與包裝了異常處理子句調用該函數。
請確保您在使用記錄器之前進行了此更換。 這個替換也可以在你的程序的其他模塊中工作。

所以,你的例子是修改這樣的: 請注意,我修改後的代碼一點,以確保異常將被生成。

def print_log_record_on_error(func): 
    def wrap(self, *args, **kwargs): 
     try: 
      return func(self, *args, **kwargs) 
     except: 
      import sys 
      print >>sys.stderr, "Unable to create log message msg=%r, args=%r " % (
       getattr(self, 'msg', '?'), getattr(self, 'args', '?')) 
      raise 
    return wrap 
import logging 
logging.LogRecord.getMessage = print_log_record_on_error(logging.LogRecord.getMessage) 

logging.basicConfig() 
my_log = logging.getLogger("MyLog") 
# this is obviously wrong 
my_log.error('%d' , "abc") 

現在它會產生更多的有用的例外:

Unable to create log message msg='%d', args=('abc',) 
Traceback (most recent call last): 
    File "C:\Progs\Python262\Lib\logging\__init__.py", line 760, in emit 
    msg = self.format(record) 
    File "C:\Progs\Python262\Lib\logging\__init__.py", line 644, in format 
    return fmt.format(record) 
    File "C:\Progs\Python262\Lib\logging\__init__.py", line 432, in format 
    record.message = record.getMessage() 
    File "C:/Users/vvlad/PycharmProjects/stackoverflow/test1.py", line 6, in wrap 
    return func(self, *args, **kwargs) 
    File "C:\Progs\Python262\Lib\logging\__init__.py", line 302, in getMessage 
    msg = msg % self.args 
TypeError: %d format: a number is required, not str 

如果您有登錄密集型應用程序,我建議增加選擇更換洛功能與否。因此,調試模式代碼將使用重載函數,但在生產中 - 它不會讓您避免性能損失的一個額外的異常處理。