【问题标题】:UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 8: ordinal not in range(128)UnicodeDecodeError:“ascii”编解码器无法解码位置 8 中的字节 0xc3:序数不在范围内(128)
【发布时间】:2022-04-15 21:30:58
【问题描述】:

我在这一行收到此错误:

logger.debug(u'__call__ with full_name={}, email={}'.format(full_name, email))

为什么?

name 变量的内容是Gonçalves

【问题讨论】:

标签: python python-2.7


【解决方案1】:

问题在于full_name 是一个str,而不是一个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)

【讨论】:

    【解决方案2】:

    这应该可以解决您的问题:

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

    问题是 unicode 字符串的默认编码是 ASCII,它只支持 128 个字符。使用 UTF-8 可以解决这个问题。

    免责声明这在细节上可能是错误的,我只在 py3 中编码。在大约 5 分钟内学会了所有这些。

    【讨论】:

    • 这似乎解决了我的问题。谢谢。
    • @quant 很高兴为您提供帮助 - 我承认我理解 poss duplicate 中链接的文档没有意义 - 我花了 4 年时间才掌握了理解令人困惑的文档的窍门。
    • @quant 在py3字符串和unicode中也是一样的,默认使用utf-8。
    【解决方案3】:

    我正在整理这个旧线程,以便提出一种解决方案,该解决方案向记录器添加上下文过滤器,从而确保在使用 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')
    

    希望这将使 python 2.x 反向移植者的生活更轻松。

    【讨论】:

      猜你喜欢
      • 2014-08-19
      • 2015-05-05
      • 2016-11-12
      • 2016-06-30
      • 2016-11-04
      • 1970-01-01
      • 2019-05-10
      • 1970-01-01
      相关资源
      最近更新 更多