问题不在于“csv
不会直接处理 UTF”;Python 中的任何内容都没有直接处理 UTF,而且您不希望它这样做。当你想要 Unicode 时,你使用 Unicode;当您需要特定的编码(无论是 UTF-8、UTF-16 还是其他)时,您必须使用字符串并手动跟踪编码。
Python 2.xcsv
不能处理 Unicode,所以排除了简单的方法。实际上,它只理解 bytes 字符串,并且总是将它们视为 ASCII。但是,除了它关心的特定字符(分隔符、引号、换行符等)之外,它不会篡改任何内容。因此,只要您使用一个字符集,其,
, "
, 和\n
(或您选择的任何特殊字符)保证被编码为与 ASCII 相同的字节,并且不会将任何其他内容编码为这些字节,您就是美好的。
当然,您不只是想以任意字符集创建 CSV 文件;您可能想在其他程序中使用它——Excel,在某处的服务器上运行的脚本,等等——并且您需要在其他程序期望的字符集中创建一个 CSV 文件。但是,如果您可以控制其他程序(例如,它是 Excel,并且您知道如何在其 Import 命令中选择字符集),那么 UTF-8 几乎总是最佳选择。
无论如何,UTF-16 不符合 CSV 友好字符集的条件,因为例如,,
它是两个字节,而不是一个。
那么,您如何处理呢?文档中的示例有答案。如果您只是复制该unicode_csv_reader
功能并与 一起使用codecs.open
,您就完成了。或者复制UnicodeReader
课程并将其传递给encoding
.
但是,如果您阅读示例代码,您会发现它是多么简单:解码您的 UTF-16,重新编码为 UTF-8,然后将其传递给reader
or DictReader
。您可以将其减少为一行额外的代码,(line.encode('utf-8') for line in infile)
. 所以:
with codecs.open(infileName , 'rU', 'utf-16') as infile:
utf8 = (line.encode('utf-8') for line in infile)
rdr = csv.DictReader(utf8, delimiter='\t')
vnames = rdr.fieldnames
for row in rdr:
do_something(row)
最后,为什么您现有的代码会引发该异常?它不在 UTF-16 解码中。这是因为您将生成的unicode
字符串传递给需要字节的代码str
。在 Python 2.x 中,这几乎总是意味着使用默认编码自动对其进行编码,默认为 ASCII,这就是引发错误的原因。这就是为什么您必须明确编码为 UTF-8。