2011-02-26 53 views
7

當我有很多使用標準Python記錄模塊不同的模塊時發現格式錯誤的根源,以下堆棧跟蹤無助於幫我找出,正好,我有一個格式錯誤的日誌語句:使用Python記錄

Traceback (most recent call last): 
    File "/usr/lib/python2.6/logging/__init__.py", line 768, in emit 
    msg = self.format(record) 
    File "/usr/lib/python2.6/logging/__init__.py", line 648, in format 
    return fmt.format(record) 
    File "/usr/lib/python2.6/logging/__init__.py", line 436, in format 
    record.message = record.getMessage() 
    File "/usr/lib/python2.6/logging/__init__.py", line 306, in getMessage 
    msg = msg % self.args 
TypeError: not all arguments converted during string formatting 

我纔剛剛開始使用Python的日誌記錄模塊,所以也許我忽視的東西明顯。我不知道如果堆棧跟蹤是無用的,因爲我使用greenlets,或者如果這是正常的日誌記錄模塊,但任何幫助,將不勝感激。我願意修改源代碼,任何可以讓日誌庫實際上給出問題出在哪裏的線索。

回答

5

日誌記錄模塊設計用於阻止錯誤的日誌消息以殺死其餘代碼,因此emit方法捕獲錯誤並將它們傳遞給方法handleError。爲你做最簡單的事情將是暫時編輯/usr/lib/python2.6/logging/__init__.py,並找到handleError。它看起來像這樣:

def handleError(self, record): 
    """ 
    Handle errors which occur during an emit() call. 

    This method should be called from handlers when an exception is 
    encountered during an emit() call. If raiseExceptions is false, 
    exceptions get silently ignored. This is what is mostly wanted 
    for a logging system - most users will not care about errors in 
    the logging system, they are more interested in application errors. 
    You could, however, replace this with a custom handler if you wish. 
    The record which was being processed is passed in to this method. 
    """ 
    if raiseExceptions: 
     ei = sys.exc_info() 
     try: 
      traceback.print_exception(ei[0], ei[1], ei[2], 
             None, sys.stderr) 
      sys.stderr.write('Logged from file %s, line %s\n' % (
          record.filename, record.lineno)) 
     except IOError: 
      pass # see issue 5971 
     finally: 
      del ei 

現在暫時編輯它。在開始插入簡單raise應保證誤差會將會傳播起來,而不是被吞噬你的代碼。一旦解決了問題,只需將日誌記錄代碼恢復到原來的狀態即可。

6

而不是編輯安裝Python代碼,你也可以找到這樣的錯誤:

def handleError(record): 
     raise RuntimeError(record) 
    handler.handleError = handleError 

其中處理器是爲有問題的處理器之一。現在,當格式錯誤發生時,你會看到位置。

+0

那麼,這是一個可怕的方法,但是,對於編輯庫完全不可能的情況,這是一種值得記住的方法,所以+1。 – porgarmingduod 2011-09-30 10:46:58

+0

@porgarmingduod:猴子補丁可能不是很好,但比操縱標準李的來源更不可怕brary。猴子補丁會影響同一進程中的其他所有內容,但直接編輯庫會影響同一系統中的其他所有內容。在Python 3.6 – 2013-01-06 23:21:49

1

或者你可以創建自己的格式,但你必須要處處包含它。

class DebugFormatter(logging.Formatter): 
    def format(self, record): 
     try: 
      return super(DebugFormatter, self).format(record) 
     except: 
      print "Unable to format record" 
      print "record.filename ", record.filename 
      print "record.lineno ", record.lineno 
      print "record.msg ", record.msg 
      print "record.args: ",record.args 
      raise 


FORMAT = '%(levelname)s %(filename)s:%(lineno)d %(message)s' 
formatter = DebugFormatter(FORMAT) 
handler = logging.StreamHandler() 
handler.setLevel(logging.DEBUG) 
handler.setFormatter(formatter) 
logger = logging.getLogger(__name__) 
logger.setLevel(logging.DEBUG) 
logger.addHandler(handler) 
3

這不是一個真正的問題的答案,但希望這將是其他像我這樣的日誌記錄模塊的初學者。

我的問題是,我替換logging.info打印的所有事件, 所以像print('a',a)有效的行成爲logging.info('a',a)(但它應該是logging.info('a %s'%a)代替。

這也暗示在How to traceback logging errors?,但它不不要出現在研究中

+1

新語法:'logging.info(f'a {A}「)' – JinSnow 2017-03-24 14:01:58

+0

感謝,我沒有看進去! https://www.python.org/dev/peps/pep-0498/ – lib 2017-03-25 11:31:46