我在这一行遇到了这个错误:
logger.debug(u'__call__ with full_name={}, email={}'.format(full_name, email))
为什么?
name
变量的内容是Gonçalves
。
我在这一行遇到了这个错误:
logger.debug(u'__call__ with full_name={}, email={}'.format(full_name, email))
为什么?
name
变量的内容是Gonçalves
。
full_name
是一个字符串,而不是Unicode对象。# -*- coding: UTF-8 -*-
import logging
logging.basicConfig()
logger = logging.getLogger()
logger.warning('testing')
# unicode.format(str) raises an error
name = 'Gonçalves'
print type(name)
print name
try:
message = u'{}'.format(name)
except UnicodeDecodeError as e:
print e
# but logger(unicode) is fine
logging.warn(u'Gonçalves')
# so unicode.format(str.decode()) doesn't raise
name = 'Gonçalves'
print type(name)
print name
message = u'{}'.format(name.decode('utf-8'))
logging.warning(message)
# and neither does unicode.format(unicode)
name = u'Gonçalves'
print type(name)
print name
message = u'{}'.format(name)
logging.warning(message)
full_name, email = [unicode(x, 'utf-8') for x in [full_name, email]]
logger.debug(u'__call__ with full_name={}, email={}'.format(full_name, email))
我重新挖掘了这个旧帖子,提出了一个解决方案,它向记录器添加了上下文过滤器,从而确保在使用Python 2.x时,传递给记录器的每个字符串都是Unicode字符串。
TL:DR; 查看帖子末尾的现成解决方案
<!-- lang: python -->
# First, let's create a string to unicode failsafe function
def safe_string_convert(string):
"""
Allows to encode strings for hacky UTF-8 logging in python 2.7
"""
try:
return string.decode('utf8')
except UnicodeDecodeError:
try:
return string.decode('unicode-escape')
except Exception:
try:
return string.decode('latin1')
except Exception:
return(b"String cannot be decoded. Passing it as binary blob" + bytes(string))
# Create a logger contextFilter class that will fix encoding for Python 2
class ContextFilterWorstLevel(logging.Filter):
"""
This class re-encodes strings passed to logger
Allows to change default logging output or record events
"""
def __init__(self):
self._worst_level = logging.INFO
if sys.version_info[0] < 3:
super(logging.Filter, self).__init__()
else:
super().__init__()
def filter(self, record):
# type: (str) -> bool
"""
A filter can change the default log output
This one simply records the worst log level called
"""
# Examples
# record.msg = f'{record.msg}'.encode('ascii', errors='backslashreplace')
# When using this filter, something can be added to logging.Formatter like '%(something)s'
# record.something = 'value'
# python 2.7 comapt fixes
if sys.version_info[0] < 3:
record.msg = safe_string_convert(record.msg)
return True
#####
# Now let's create a new logger and try it
#####
log_filter = ContextFilterWorstLevel()
logger = logging.getLogger()
# Remove earlier handlers if exist
while _logger.handlers:
_logger.handlers.pop()
# Add context filter
logger.addFilter(log_filter)
# Test
logger.info('Café non unicode string")
可直接使用的解决方案: ofuntions.logger_utils 包。
使用 pip install ofunctions.logger_utils
进行安装。
用法:
from ofunctions.logger_utils import logger_get_logger
logger = logger_get_logger(log_file='somepath')
logger.info('Café non unicode')
full_name
和email
变量已经是 Unicode 吗?如果不是,请在预处理之前将它们转换为 Unicode。这可能会(很可能)在其他地方引发错误,但更容易捕获。 - Legorooj