Python 将UTF bytestream强制为ASCII

Python 将UTF bytestream强制为ASCII,python,csv,python-2.7,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) 是否有一种方法可以处理来自infle的字节流,将其强制转换为ascii,然后再将其移交给csv.DictReader?谢谢 with( codecs.ope

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

 UnicodeEncodeError: 'ascii' codec can't encode character u'\xed' in position 121: ordinal not in range(128)
是否有一种方法可以处理来自infle的字节流,将其强制转换为ascii,然后再将其移交给
csv.DictReader
?谢谢

 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)
问题不在于“
csv
不会直接处理UTF”;Python中没有任何东西可以直接处理UTF,您也不希望它这样做。如果需要Unicode,则使用Unicode;当需要特定编码(无论是UTF-8、UTF-16还是其他编码)时,必须使用字符串并手动跟踪编码


Python2.x
csv
无法处理Unicode,因此排除了简单的方法。事实上,它只理解字节字符串,并且总是将它们视为ASCII。但是,除了它关心的特定字符(分隔符、引号、换行符等)之外,它不会篡改任何内容。因此,只要您使用的字符集的
”和
\n
(或您选择的任何特殊字符)保证编码到与ASCII相同的字节,并且不会将任何其他字符编码到这些字节,就可以了

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

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


那么,您如何处理这个问题呢?文档中的有答案。如果您只是复制
unicode\u csv\u reader
函数并将其与
编解码器一起使用。打开
,您就完成了。或者复制
UnicodeReader
类并将其传递给
编码

但是,如果你阅读示例代码,你会发现它是多么微不足道:解码UTF-16,重新编码为UTF-8,然后将其传递给
读卡器
读卡器
。你可以将其减少为一行额外的代码,
(line.encode('UTF-8')用于内嵌的行)
。因此:

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。

csv
模块仍然只处理ByTestRing;它试图将unicode值编码回字节字符串。换句话说,您的方法永远不会起作用。请使用常规的
Open()
将文件作为ByTestStream打开您的意思是“删除任何非7位字符”,这并不难做到。提示:
ord()
@MartijnPieters:用常规的
open
打开它是行不通的。
csv
只处理ASCII兼容的字节字符串;UTF-16不合格。@abarnert:是的,我意识到了;我正在考虑把它当作一个复制品。谢谢abarnert,Martijn。这太费劲了;我对编码处理的想法已经结束了。我会的逐步完成这个过程。@user2808321:您几乎总是必须仔细考虑编码过程,尤其是当您的输入和输出字符集是非ASCII友好的,如UTF-16时。当然,除非您升级到Python 3.x。