Python:Logging TypeError:并非在字符串格式化期间转换所有参数

时间:2021-10-08 04:17:20

Here is what I am doing

这就是我在做的事情

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

My python version is

我的python版本是

$ python --version
Python 2.7.3

How do I make it work?

我如何使其工作?

4 个解决方案

#1


17  

You could do the formatting yourself:

你可以自己做格式化:

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

As was pointed out by Martijn Pieters, this will always run the string formatting, while using the logging module would cause the formatting to only be performed if the message is actually logged.

正如Martijn Pieters所指出的,这将始终运行字符串格式化,而使用日志记录模块将导致仅在实际记录消息时才执行格式化。

#2


35  

You cannot use new-style formatting when using the logging module; use %s instead of {}.

使用日志记录模块时,不能使用新式格式;使用%s而不是{}。

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

The logging module uses the old-style % operator to format the log string. See the debug method for more detail.

日志记录模块使用旧式%运算符来格式化日志字符串。有关更多详细信息,请参阅调试方法

If you really want to use str.format() string formatting, consider using custom objects that apply the formatting 'late', when actually converted to a string:

如果您确实想使用str.format()字符串格式,请考虑使用在实际转换为字符串时应用格式“late”的自定义对象:

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

This is an approach the Python 3 logging module documentation proposes, and it happens to work on Python 2 too.

这是Python 3日志记录模块文档提出的方法,它也适用于Python 2。

#3


6  

Martijn's answer is correct, but if you prefer to use new style formatting with logging, it can be accomplished by subclassing Logger.

Martijn的答案是正确的,但是如果您更喜欢使用新的格式化日志,那么可以通过子类化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

Then just set the logging class:

然后只需设置日志记录类:

logging.setLoggerClass(Logger)

#4


0  

You could do also (Python 3);

你也可以(Python 3);

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

#1


17  

You could do the formatting yourself:

你可以自己做格式化:

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

As was pointed out by Martijn Pieters, this will always run the string formatting, while using the logging module would cause the formatting to only be performed if the message is actually logged.

正如Martijn Pieters所指出的,这将始终运行字符串格式化,而使用日志记录模块将导致仅在实际记录消息时才执行格式化。

#2


35  

You cannot use new-style formatting when using the logging module; use %s instead of {}.

使用日志记录模块时,不能使用新式格式;使用%s而不是{}。

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

The logging module uses the old-style % operator to format the log string. See the debug method for more detail.

日志记录模块使用旧式%运算符来格式化日志字符串。有关更多详细信息,请参阅调试方法

If you really want to use str.format() string formatting, consider using custom objects that apply the formatting 'late', when actually converted to a string:

如果您确实想使用str.format()字符串格式,请考虑使用在实际转换为字符串时应用格式“late”的自定义对象:

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

This is an approach the Python 3 logging module documentation proposes, and it happens to work on Python 2 too.

这是Python 3日志记录模块文档提出的方法,它也适用于Python 2。

#3


6  

Martijn's answer is correct, but if you prefer to use new style formatting with logging, it can be accomplished by subclassing Logger.

Martijn的答案是正确的,但是如果您更喜欢使用新的格式化日志,那么可以通过子类化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

Then just set the logging class:

然后只需设置日志记录类:

logging.setLoggerClass(Logger)

#4


0  

You could do also (Python 3);

你也可以(Python 3);

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