我正在调试调试模块,并且依靠try ... catch来检测TypeError并正确记录我的消息的格式,然后,我注意到当传递字典时,Python不会引发传统异常。
>>> 'var' % {1: 'variable'}
'var'
>>> 'var' % (1,)
Traceback (most recent call last):
File "<string>", line 1, in <module>
这是使用日志记录模块的最小示例:
import logging
class SmartLogRecord(logging.LogRecord):
def _getMessage(self, remaining_arguments):
try:
if self.args:
remaining_arguments.append( self.msg % self.args )
else:
remaining_arguments.append( self.msg )
return False
except TypeError as error:
last = self.args[-1]
self.args = self.args[:-1]
remaining_arguments.append( str( last ) )
if len( self.args ):
return True
else:
remaining_arguments.append( self.msg )
return False
def getMessage(self):
"""
Return the message for this LogRecord.
Return the message for this LogRecord after merging any user-supplied
arguments with the message.
"""
remaining_arguments = []
self.msg = str( self.msg )
while self._getMessage( remaining_arguments ): pass
return " ".join( reversed( remaining_arguments ) )
logging.setLogRecordFactory(SmartLogRecord)
var = 'SmartLogRecord'
logging.warning('I am a', var)
dumb = {1: 'variable'}
logging.warning('I am a', dumb)
运行它会得到:
WARNING:root:I am a SmartLogRecord
WARNING:root:I am a
您会注意到,上一条dumb
消息丢失了。
答案 0 :(得分:1)
我认为观察到的行为符合docs。
如果format需要单个参数,则值可能是单个非元组 宾语。 [5]否则,值必须是一个具有正确数字的元组 由格式字符串或单个映射对象指定的项 (例如,字典)。
注意[5]:
仅格式化一个元组,因此应提供一个单例元组 其唯一的元素是要格式化的元组。
这说明仅当元组与格式字符串要求完全匹配时,才可接受该元组。具有一项本身不是元组的项的元组可能无法匹配任何格式字符串,并且总是引发异常。
它还解释了dict始终被接受为一种类型,但可能会产生其他错误。
就我错了的情况而言,您有可能会发现另一个“怪癖”。他们明确警告:
此处描述的格式化操作表现出各种怪癖 导致许多常见错误(例如无法显示) 元组和字典正确)。使用较新的格式化字符串 文字或str.format()接口有助于避免这些错误。
答案 1 :(得分:0)
作为解决此问题的方法,我提出了以下解决方案:
@include namespace(cool, '+', stuff) {
color: green;
}
@include namespace(stuff, '~', things) {
color: red;
}
@include namespace(stuff, '*:not(.lame)', things) {
color: red;
}
哪个可以正常运行:
import sys
import logging
if sys.version_info[0] < 3:
is_python2 = True
from collections import MutableMapping
else:
from collections.abc import MutableMapping
class SmartLogRecord(logging.LogRecord):
def _getMessage(self, remaining_arguments):
try:
args = self.args
if args:
# if isinstance( args, dict ):
if isinstance( args, MutableMapping ):
new_msg = self.msg % args
if new_msg == self.msg:
remaining_arguments.append( str( args ) )
remaining_arguments.append( new_msg )
else:
remaining_arguments.append( new_msg )
else:
remaining_arguments.append( self.msg % args )
else:
remaining_arguments.append( self.msg )
return False
except TypeError as error:
self.args = args[:-1]
remaining_arguments.append( str( args[-1] ) )
if len( args ) - 1 > 0:
return True
else:
remaining_arguments.append( self.msg )
return False
def getMessage(self):
"""
Return the message for this LogRecord.
Return the message for this LogRecord after merging any user-supplied
arguments with the message.
"""
remaining_arguments = []
self.msg = str( self.msg )
while self._getMessage( remaining_arguments ): pass
return " ".join( reversed( remaining_arguments ) )
logging.setLogRecordFactory(SmartLogRecord)
var = 'SmartLogRecord'
logging.warning('I am a', var)
dumb = {1: 'variable'}
logging.warning('I am a', dumb)