2014-01-15 41 views
2

如何将utf-8字符写入csv文件?将utf-8格式的Python列表写入CSV

我的数据和代码:

# -*- coding: utf-8 -*- 

l1 = ["žžž", "ččč"] 
l2 = ["žžž", "ččč"] 

thelist = [l1, l2] 

import csv 
import codecs 

with codecs.open('test', 'w', "utf-8-sig") as f: 
    writer = csv.writer(f) 
    for x in thelist: 
     print x 
     for mem in x: 
      writer.writerow(mem) 

错误消息:

Traceback (most recent call last): 
    File "2010rudeni priimti.py", line 263, in <module> 
writer.writerow(mem) 
File "C:\Python27\lib\codecs.py", line 691, in write 
return self.writer.write(data) 
File "C:\Python27\lib\codecs.py", line 351, in write 
data, consumed = self.encode(object, self.errors) 
File "C:\Python27\lib\encodings\utf_8_sig.py", line 82, in encode 
return encode(input, errors) 
File "C:\Python27\lib\encodings\utf_8_sig.py", line 15, in encode 
return (codecs.BOM_UTF8 + codecs.utf_8_encode(input, errors)[0], len(input)) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 11: ordinal not in range(128) 

按任意键继续。 。 。

我的错误是什么?

+0

作为一个说明,你还没有为你的源代码指定一个编码,这意味着Python将把它解释为Latin-1(可能带有警告,但我想你要么没有看到它,要么忽略它它?)...但是你显然将它编辑为不同的东西,因为Latin-1中没有'ž'字符。所以,即使你解决了当前的问题,你也只需要将文件写入mojibake。例如,如果您使用的是UTF-8编辑器,那么第一个字符串将最终成为'žžž'。 – abarnert

+0

'CHARSET =“$(file -bi”$ i“| awk -F”=“'{print $ 2}')” if [“$ CHARSET”!= utf-8];然后 iconv -f“$ CHARSET”-t utf8“$ i”-o outfile fi' – Vor

回答

5

2.x中的csv模块不读取/写入Unicode,它读取/写入字节(并假定它们与ASCII兼容,但UTF-8不存在问题)。

所以,当你给它一个codecs Unicode文件要写入,它通过str而不是unicode。并且当codecs尝试使用UTF-8的encode时,它必须首先将其转换为Unicode,为此它使用默认编码(即ASCII码),该编码会失败。因此,这个错误:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 11: ordinal not in range(128) 

该解决方案在文档说明,在Examples一个包装,照顾一切的为您服务。使用UnicodeWriter与纯二进制文件,而不是使用codecs文件。


作为替代方案,也有PyPI上的几个不同的软件包收官csv模块直接unicode而不是str处理,像unicodecsv

作为一个更激进的选择,Python 3.x的csv模块首先不存在这个问题(3.x也没有下一个问题)。

一个黑客的替代方案就是假装整个世界都是UTF-8。毕竟,你的源代码和你的输出都是UTF-8,csv模块并不关心任何东西,只是少数字符(换行符,逗号,也许引号和反斜杠)与ASCII兼容。所以你可以完全跳过解码和编码,一切都会工作。这里明显的缺点是,如果出现任何错误,而不是发生错误以进行调试,则会得到一个充满垃圾的文件。


还有其他两个问题与您的代码,这两者都不UnicodeWriterunicodecsv能神奇固定(尽管Python 3中可以固定第一)。

首先,你实际上并不是,而是模块的Unicode第一位。源数据中的列是普通的旧的str文字,如"žžž"。您无法将其编码为UTF-8,或者您可以,但只能通过先将其自动解码为ascii,这将再次导致相同的错误。使用Unicode文字(如u"žžž")来避免这种情况(或者,如果您愿意,可以从源代码中明确地使用decode ......但这很愚蠢)。

其次,您尚未在源代码中指定encoding declaration,但您已使用非ASCII字符。从技术上讲,这在Python 2.7中是非法的。实际上,我很确定它会给你一个警告,但是会将你的源代码视为Latin-1。这是不好的,因为你显然没有使用Latin-1编辑器(你不能将ž放在Latin-1文本文件中,因为没有这样的字符)。如果您将文件保存为UTF-8,然后告诉Python将其解释为Latin-1,那么最终将以žžž而不是žžž以及类似的mojibake结束。

+0

@abamert,我试过了代码,它没有工作。如果您不介意查看https://stackoverflow.com/questions/49121728/write-utf-8-through-python-csv-prev-answer-not-working,我将不胜感激您的任何评论。 – WesR