2012-10-11 30 views
18

Aquí es lo que estoy haciendoPython: Inicio de sesión TypeError: no todos los argumentos convertidos en formato de cadenas

>>> 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 
>>> 

Mi versión Python es

$ python --version 
Python 2.7.3 

¿Cómo hacer que funcione?

Respuesta

10

Usted podría hacer el formateo de sí mismo:

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

Como se ha señalado por Martijn Pieters, esto será siempre ejecutar el formateo de cadenas, mientras se utiliza el módulo de registro causaría el formato que sólo se realiza si el mensaje en realidad está registrado.

+15

¿Conoce que al hacer el formateo de ti mismo, de que pierda la ventaja de la velocidad ofrecida al permitir que el módulo de registro hacemos por ti * sólo cuando el mensaje es realmente registrado *. En otras palabras, si usa el controlador 'debug()' pero el nivel de registro excluye el nivel DEBUG, no incurre en la penalización de la operación de formateo de cadenas. La diferencia de velocidad puede ser significativa si tiene muchos mensajes de depuración. –

32

No puede usar el formato de estilo nuevo cuando usa el módulo de registro; use %s en lugar de {}.

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

El módulo de registro utiliza el viejo estilo % operador para dar formato a la cadena de registro. Vea el debug method para más detalles.

Si realmente desea utilizar str.format() formato de cadenas, considerar el uso de objetos personalizados que se aplican el formato 'tarde', cuando en realidad convierte en una cadena:

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)) 

Este es un enfoque del Python 3 logging module documentation proposes, y sucede para trabajar en Python 2 también.

6

La respuesta de Martijn es correcta, pero si prefiere usar el nuevo estilo de formateo con el registro, se puede lograr subclasificando Logger.

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 

Entonces acaba de establecer la clase de registro:

logging.setLoggerClass(Logger) 
+0

O incluso (al menos en Python 3.5) use solo LogRecord con 'logging.setLogRecordFactory (LogRecord)' –

Cuestiones relacionadas