web-dev-qa-db-fra.com

Python: Logging TypeError: pas tous les arguments convertis lors du formatage de chaîne

Voici ce que je fais

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

Ma version python est 

$ python --version
Python 2.7.3

Comment puis-je le faire fonctionner?

23
daydreamer

Vous pouvez faire le formatage vous-même:

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

Comme l'a souligné Martijn Pieters, le formatage de la chaîne sera toujours exécuté, tandis que l'utilisation du module de journalisation entraînerait le formatage uniquement si le message est réellement enregistré. 

17
Matt

Vous ne pouvez pas utiliser la mise en forme de nouveau style lorsque vous utilisez le module de journalisation; utilisez %s au lieu de {}.

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

Le module de journalisation utilise l'opérateur % de style ancien pour formater la chaîne de journalisation. Voir la méthode debug pour plus de détails.

Si vous voulez vraiment utiliser la mise en forme de chaîne str.format(), envisagez d'utiliser des objets personnalisés qui appliquent la mise en forme 'en retard', lorsqu'ils sont convertis en chaîne:

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

C’est une approche que la documentation du module Python 3 logging propose , et il se trouve qu’il fonctionne également sur Python 2.

37
Martijn Pieters

La réponse de Martijn est correcte, mais si vous préférez utiliser un nouveau format de style avec la journalisation, vous pouvez le faire en sous-classant 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

Ensuite, définissez la classe de journalisation:

logging.setLoggerClass(Logger)
6
Jeff-Meadows

Vous pourriez faire aussi (Python 3);

logging.info(f'date={date}')
0
yusuf