将UTF字节流强制转换为ASCII

时间:2013-10-01 17:57:44

标签: python csv python-2.7

我知道csv不会直接处理UTF,解决方案的一部分是使用codecs打开文件,使用正确的编码打开流。我仍然得到错误:

 UnicodeEncodeError: 'ascii' codec can't encode character u'\xed' in position 121: ordinal not in range(128)

有没有办法处理来自infile的字节流,在将其移交给csv.DictReader之前将其强制转换为ascii?感谢。

 with( codecs.open( infileName , 'rU', 'utf-16') ) as infile:
     rdr = csv.DictReader( infile , delimiter='\t' )
     vnames = rdr.fieldnames
     for row in rdr:
         do_something(row)

1 个答案:

答案 0 :(得分:1)

问题不在于“csv不会直接处理UTF”; Python中的 nothing 直接处理UTF,你不会想要它。如果需要Unicode,可以使用Unicode;当您需要特定编码(无论是UTF-8,UTF-16还是其他)时,您必须使用字符串并手动跟踪编码。


Python 2.x csv无法处理Unicode,因此排除了简单的方法。实际上,它只能理解字节字符串,并始终将它们视为ASCII。但是,除了它所关注的特定字符(分隔符,引号,换行符等)之外,它不会篡改任何其他内容。因此,只要您使用其,"\n(或您选择的任何特殊字符)的字符集,就可以保证编码为与ASCII相同的字节,没有别的东西可以编码到那些字节,你没事。

当然,您不只是想在任意字符集中创建CSV文件;你可能想要在其他程序中使用它 - Excel,在某个服务器上运行的脚本,无论如何 - 你需要在其他程序所期望的charset中创建一个CSV文件。但是,如果您可以控制其他程序(例如,它是Excel,并且您知道如何在其“导入”命令中选择字符集),则UTF-8几乎总是最佳选择。

无论如何,UTF-16不符合CSV友好的字符集,因为例如,是两个字节,而不是一个字节。


那么,你怎么处理这个?文档中的Examples有答案。如果您只是复制unicode_csv_reader功能并将其与codecs.open一起使用,那么您就完成了。或者复制UnicodeReader课程并将其传递给encoding

但是如果您阅读了示例的代码,您可以看到它是多么的微不足道:解码您的UTF-16,重新编码为UTF-8,并将其传递给reader或{{1} }。您可以将其减少到一行额外的代码DictReader。所以:

(line.encode('utf-8') for line in infile)

最后,为什么您现有的代码会引发该异常?它不是UTF-16解码。这是因为您将生成的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) 字符串传递给需要字节unicode的代码。在Python 2.x中,这几乎总是意味着使用默认编码自动对其进行编码,默认编码默认为ASCII,这就是引发错误的原因。这就是你必须明确编码为UTF-8的原因。