it-swarm.com.de

Python: Logging TypeError: Nicht alle während der String-Formatierung konvertierten Argumente

Hier ist was ich mache

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

Meine Python-Version ist 

$ python --version
Python 2.7.3

Wie mache ich das?

23
daydreamer

Sie können die Formatierung selbst vornehmen:

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

Wie von Martijn Pieters ausgeführt, führt dies immer die Formatierung der Zeichenfolge aus, während die Verwendung des Protokollierungsmoduls dazu führen würde, dass die Formatierung nur durchgeführt wird, wenn die Nachricht tatsächlich protokolliert wird. 

17
Matt

Sie können die Formatierung im neuen Stil nicht verwenden, wenn Sie das Protokollierungsmodul verwenden. Verwenden Sie %s anstelle von {}.

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

Das Protokollierungsmodul verwendet den Operator % des alten Stils, um die Protokollzeichenfolge zu formatieren. Weitere Informationen finden Sie in der debug-Methode .

Wenn Sie wirklich die str.format()-Zeichenkettenformatierung verwenden möchten, sollten Sie benutzerdefinierte Objekte verwenden, die die Formatierung 'spät' anwenden, wenn Sie sie tatsächlich in eine Zeichenfolge konvertieren:

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

Dies ist ein Ansatz, den die Dokumentation des Moduls Python 3 logging vorschlägt, und sie funktioniert auch auf Python 2.

37
Martijn Pieters

Martijns Antwort ist korrekt. Wenn Sie jedoch die neue Formatierung mit der Protokollierung bevorzugen, können Sie dies durch die Unterklasse von Logger erreichen.

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

Dann legen Sie einfach die Protokollierungsklasse fest:

logging.setLoggerClass(Logger)
6
Jeff-Meadows

Sie könnten auch (Python 3) tun;

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