6.10.4 错误处理
前面几节指出,读写Unicode文件时需要知道所使用的编码。正确地设置编码很重要,这有两个原因:首先,如果读文件时未能正确地配置编码,就无法正确地解释数据,数据有可能被破坏或者无法解码;其次,并不是所有Unicode字符都可以用所有编码表示,所以如果写文件时使用了错误的编码,就会产生一个错误,可能丢失数据。类似于str的encode()方法和bytes的decode()方法,codecs也还有了同样的5个错误处理选项,如表6-1所列。
表6-1 Codec错误处理模式
错误模式 | 概述 |
---|---|
strict | 如果数据无法转换,则产生一个异常 |
replace | 将无法编码的数据替换为一个特殊的标志字符 |
ignore | 跳过数据 |
xmlcharrefreplace | XML字符(仅适用于编码) |
backslashreplace | 转义序列(仅适用于编码) |
6_10_4_1_编码错误
最常见的错误是在向一个ASCII输出流(如一个常规文件或sys.stdout)写Unicode数据时接收到一个UnicodeEncodeError。代码清单6-101中的示例程序可以用来试验不同的错误处理模式。
import codecs
import sys
error_handling = sys.argv[1]
text = 'fráncais'
try:
# Save the data,encoded as ASCII,using the error
# handling mode specified on the command line.
with codecs.open('encode_error.txt','w',
encoding='ascii',
errors=error_handling) as f:
f.write(text)
except UnicodeEncodeError as err:
print('ERROR:',err)
else:
# If there was no error writing to the file,
# show the file's contents.
with open('encode_error.txt','rb') as f:
print('File contents: {!r}'.format(f.read()))
要确保一个应用显式地为所有I/O操作设置正确的编码,strict模式是最安全的选择,但是产生一个异常时,这种模式可能导致程序崩溃。
另外一些错误模式更为灵活。例如,replace确保不会产生任何错误,其代价是一些无法转换为所需编码的数据可能会丢失。pi(π)的Unicode字符仍然无法用ASCII编码,但是采用这种错误处理模式时,并不是产生一个异常,而是会在输出中将这个字符替换为?。
要完全跳过有问题的数据,可以使用ignore。无法编码的数据都会被丢弃。
还有两种无损的错误处理选项,这两种模式会把字符替换为标准中定义的一个与该编码不同的候选表示。xmlcharrefreplace使用一个XML字符引用作为替代(W3C文档“字符的XML实体定义”中指定了字符引用列表)。
另一种无损的错误处理机制是backslashreplace,它生成的输出格式类似于打印unicode对象的repr()时返回的值。Unicode字符会被替换为\u以及码点的十六进制值。