以下是问题的快速重现:
>>> 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
>>>
如何让它发挥作用?
这实际上是 为什么我在尝试使用 % 替换像 {0} 这样的占位符时会收到“TypeError:并非所有参数都在字符串格式化期间转换”? - 但因为实际的格式化步骤发生在用户代码之外,需要不同的解决方法。
使用日志模块时不能使用新式格式;使用
%s
代替 {}
。
logging.info('date=%s', date)
日志记录模块使用旧式的
%
运算符来格式化日志字符串。有关更多详细信息,请参阅 debug
方法。
如果您确实想使用
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))
这是 Python 3
logging
模块文档提出的一种方法,它也恰好适用于 Python 2。
您可以自己进行格式化:
logging.info('date={}'.format(date))
正如 Martijn Pieters 所指出的,这将始终运行字符串格式化,而使用日志记录模块将导致仅在实际记录消息时才执行格式化。
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
然后只需设置日志记录类别:
logging.setLoggerClass(Logger)
你也可以这样做(Python 3);
logging.info(f'date={date}')
如果您更熟悉打印语句,请直接打印到记录器中
logging.info(print("Test:" , variable))