关于编码:用python创建一个utf-8 csv文件

Create an utf-8 csv file in Python

我不能用python创建utf-8csv文件。

我正在读它的文档,在示例部分,它说:

For all other encodings the following
UnicodeReader and UnicodeWriter
classes can be used. They take an
additional encoding parameter in their
constructor and make sure that the
data passes the real reader or writer
encoded as UTF-8:

好啊。所以我有这个代码:

1
2
3
4
values = (unicode("?","utf-8"), unicode("é","utf-8"))
f = codecs.open('eggs.csv', 'w', encoding="utf-8")
writer = UnicodeWriter(f)
writer.writerow(values)

我不断得到这个错误:

1
2
3
4
5
6
7
line 159, in writerow
    self.stream.write(data)
  File"/usr/lib/python2.6/codecs.py", line 686, in write
    return self.writer.write(data)
  File"/usr/lib/python2.6/codecs.py", line 351, in write
    data, consumed = self.encode(object, self.errors)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 22: ordinal not in range(128)

有人能给我一盏灯吗?这样我就可以理解我到底做错了什么,因为我在调用unicodewriter类之前设置了所有的编码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class UnicodeWriter:
   """
    A CSV writer which will write rows to CSV file"f",
    which is encoded in the given encoding.
   """


    def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
        # Redirect output to a queue
        self.queue = cStringIO.StringIO()
        self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
        self.stream = f
        self.encoder = codecs.getincrementalencoder(encoding)()

    def writerow(self, row):
        self.writer.writerow([s.encode("utf-8") for s in row])
        # Fetch UTF-8 output from the queue ...
        data = self.queue.getvalue()
        data = data.decode("utf-8")
        # ... and reencode it into the target encoding
        data = self.encoder.encode(data)
        # write to the target stream
        self.stream.write(data)
        # empty queue
        self.queue.truncate(0)

    def writerows(self, rows):
        for row in rows:
            self.writerow(row)


您不必使用codecs.openUnicodeWriter接受unicode输入并负责将所有内容编码为utf-8。当UnicodeWriter写入您传递给它的文件句柄时,所有内容都已经是UTF-8编码的(因此它与您用open打开的普通文件一起工作)。

通过使用codecs.open,您基本上将Unicode对象转换为UnicodeWriter中的utf-8字符串,然后再次尝试将这些字符串重新编码为utf-8,就好像这些字符串包含Unicode字符串一样,但显然失败了。


不久前我遇到了csv/unicode挑战,把它扔到了bitback上:http://bitback.org/famousactrress/dude_csv.。如果你的需求很简单,可能对你有用:)


正如你所理解的,如果你使用纯开放的方式,它会起作用。

原因是您试图对UTF-8进行两次编码。一次

1
f = codecs.open('eggs.csv', 'w', encoding="utf-8")

然后在unicodewriter.writerow中

1
2
# ... and reencode it into the target encoding
data = self.encoder.encode(data)

要检查这是否有效,请使用您的原始代码并在该行外注释。

格雷茨


你不需要"双重编码"一切。

您的应用程序应该完全使用Unicode。

只在codecs.open中进行编码,将utf-8字节写入外部文件。不要在应用程序中使用其他编码。