2012-10-11 17 views
18

स्वरूपण यहाँ दौरान परिवर्तित क्या मैंपायथन: लॉगिंग लेखन त्रुटि: नहीं सभी तर्क स्ट्रिंग

>>> 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 --version 
Python 2.7.3 

है?

उत्तर

10

आप कर सकता है अपने आप को स्वरूपण:

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

के रूप में मार्टिन पीटर्स द्वारा बताया गया, यह हमेशा स्ट्रिंग स्वरूपण, चलाने, जबकि प्रवेश मॉड्यूल का उपयोग करने के संदेश अगर केवल प्रदर्शन किया जा स्वरूपण का कारण होता होगा वास्तव में लॉग इन है।

+15

जानते हैं अपने आप स्वरूपण करके, आप ढीला है कि गति लाभ लॉगिंग मॉड्यूल दे द्वारा की पेशकश की यह तुम्हारे लिए क्या संदेश है * केवल जब वास्तव में लॉग *। दूसरे शब्दों में, यदि आप 'डीबग()' हैंडलर का उपयोग करते हैं लेकिन लॉगिंग स्तर 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 है, और ऐसा होता है पायथन 2 पर भी काम करने के लिए।

6

मार्टिजन का जवाब सही है, लेकिन यदि आप लॉगिंग के साथ नई शैली स्वरूपण का उपयोग करना पसंद करते हैं, तो यह लॉगर को उपclassing द्वारा पूरा किया जा सकता है।

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

या यहां तक ​​कि (कम से कम पायथन 3.5 पर) केवल logRecord का उपयोग 'logging.setLogRecordFactory (LogRecord) ' –