2012-10-11 69 views
18

這裏轉換期間的所有參數是我在做什麼的Python:登錄類型錯誤:不是字符串格式化

>>> import logging 
>>> logging.getLogger().setLevel(logging.INFO) 
>>> from datetime import date 
>>> date = date.today() 
>>> logging.info('date={}', date) 
Traceback (most recent call last): 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/logging/__init__.py", line 846, in emit 
    msg = self.format(record) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/logging/__init__.py", line 723, in format 
    return fmt.format(record) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/logging/__init__.py", line 464, in format 
    record.message = record.getMessage() 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/logging/__init__.py", line 328, in getMessage 
    msg = msg % self.args 
TypeError: not all arguments converted during string formatting 
Logged from file <stdin>, line 1 
>>> 

我的Python版本

$ python --version 
Python 2.7.3 

我如何工作的呢?

回答

10

你可以做的格式化自己:

logging.info('date={}'.format(date)) 

正如由馬亭皮特斯指出,這將始終運行字符串格式化,同時利用記錄模塊將導致格式化到如果消息只進行實際上被記錄。

+15

知道,通過執行格式化自己,你失去通過讓記錄模塊所提供的速度優勢爲你做*只有當消息實際記錄*。換句話說,如果您使用'debug()'處理程序,但日誌記錄級別不包含DEBUG級別,則不會招致字符串格式化操作的損失。如果您有很多調試消息,則速度差異可能很大。 –

32

使用記錄模塊時不能使用新式格式;使用%s而不是{}

logging.info('date=%s', date) 

記錄模塊使用舊式%運營商格式的日誌字符串。有關更多詳細信息,請參見debug method

如果你真的想用str.format()字符串格式化,請考慮使用應用的格式自定義對象「晚」的時候,居然轉換爲字符串:

class BraceMessage(object): 
    def __init__(self, fmt, *args, **kwargs): 
     self.fmt = fmt 
     self.args = args 
     self.kwargs = kwargs 

    def __str__(self): 
     return self.fmt.format(*self.args, **self.kwargs) 

__ = BraceMessage 

logging.info(__('date={}', date)) 

這是一種方法的Python 3 logging module documentation proposes,和它發生也可以使用Python 2。

6

Martijn的回答是正確的,但如果你喜歡使用新的格式與日誌記錄,它可以通過子類化記錄器來完成。

import logging 

class LogRecord(logging.LogRecord): 
    def getMessage(self): 
     msg = self.msg 
     if self.args: 
      if isinstance(self.args, dict): 
       msg = msg.format(**self.args) 
      else: 
       msg = msg.format(*self.args) 
     return msg 

class Logger(logging.Logger): 
    def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None): 
     rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func) 
     if extra is not None: 
      for key in extra: 
       rv.__dict__[key] = extra[key] 
     return rv 

然後,只需設置日誌類:

logging.setLoggerClass(Logger) 
+0

甚至(至少在Python 3.5上)只用LogRecord和'logging.setLogRecordFactory(LogRecord)' –