设置Python中的隐式默认编码\解码错误处理

2 投票
2 回答
1384 浏览
提问于 2025-04-16 02:01

我正在处理一些用latin1编码的外部数据。所以我添加了一个叫 sitecustomize.py 的文件,并在里面加了以下内容:

sys.setdefaultencoding('latin_1') 

果然,现在处理latin1字符串时一切正常。

但是,如果我遇到一些不是用latin1编码的内容:

s=str(u'abc\u2013')

我就会收到一个错误:UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2013' in position 3: ordinal not in range(256)

我希望的是,无法编码的字符能被简单地忽略,也就是说在上面的例子中我希望得到 s=='abc?',而且不想每次都明确调用 decode()encode,也就是不想在每次调用时都写 s.decode(...,'replace')

我尝试过用 codecs.register_error 做不同的事情,但都没有成功。

请帮帮我?

2 个回答

1

你可以定义自己的处理器,然后用它来做你想做的事情。看看这个例子:

import codecs
from logging import getLogger

log = getLogger()

def custom_character_handler(exception):
    log.error("%s for %s on %s from position %s to %s. Using '?' in-place of it!",
            exception.reason,
            exception.object[exception.start:exception.end],
            exception.encoding,
            exception.start,
            exception.end )
    return ("?", exception.end)

codecs.register_error("custom_character_handler", custom_character_handler)

print( b'F\xc3\xb8\xc3\xb6\xbbB\xc3\xa5r'.decode('utf8', 'custom_character_handler') )
print( codecs.encode(u"abc\u03c0de", "ascii", "custom_character_handler") )

运行这个代码后,你会看到:

invalid start byte for b'\xbb' on utf-8 from position 5 to 6. Using '?' in-place of it!
Føö?Bår
ordinal not in range(128) for π on ascii from position 3 to 4. Using '?' in-place of it!
b'abc?de'

参考资料:

  1. https://docs.python.org/3/library/codecs.html#codecs.register_error
  2. https://docs.python.org/3/library/exceptions.html#UnicodeError
  3. 如何忽略文件中的无效行?
  4. 'str' 对象没有 'decode' 属性。Python 3 错误?
  5. 如何在 Python 中替换字符串中的无效 Unicode 字符?
  6. 在 Python 中读取文件时遇到 UnicodeDecodeError,如何忽略错误并跳到下一行?
2

脚本不能调用 sys.setdefaultencoding 是有原因的。不要这样做,因为一些库(包括 Python 自带的标准库)期望默认编码是 'ascii'。

相反,当你把字符串读入程序时(比如通过文件、标准输入、网络等),要明确地将它们解码成 Unicode;而在输出字符串时,也要明确地进行编码。

明确解码时需要一个参数,用来指定如何处理那些无法解码的字节。

撰写回答