将 utf-8 格式的 Python 列表写入 CSV

Posted

技术标签:

【中文标题】将 utf-8 格式的 Python 列表写入 CSV【英文标题】:Writing utf-8 formated Python lists to CSV 【发布时间】:2014-02-03 07:01:09 【问题描述】:

如何将 utf-8 字符写入 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)

按任意键继续。 . .

我的错误是什么?

【问题讨论】:

附带说明,您没有为源代码指定编码,这意味着 Python 会将其解释为 Latin-1(可能带有警告,但我猜您要么没有看到或忽略它?)...但您显然将其编辑为不同的东西,因为 is 在 Latin-1 中没有 ž 字符。因此,即使您解决了当前问题,您也只需将 mojibake 写入文件。例如,如果您使用的是 UTF-8 编辑器,则第一个字符串将以 žžž 结尾。 CHARSET="$(file -bi "$i"|awk -F "=" 'print $2')" if [ "$CHARSET" != utf-8 ]; then iconv -f "$CHARSET" -t utf8 "$i" -o outfile fi 【参考方案1】:

2.x 中的 csv 模块不读/写 Unicode,它读/写字节(并假设它们是 ASCII 兼容的,但这不是 UTF-8 的问题)。

所以,当你给它一个codecs Unicode 文件来写入时,它会传递一个str 而不是unicode。当codecs 尝试将encode 转换为UTF-8 时,它必须首先将decode 转换为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 可以修复第一个)。

首先,您实际上并没有提供 csv 模块 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。

【讨论】:

@abamert,我尝试了代码,但它不起作用。如果您不介意查看***.com/questions/49121728/…,我将不胜感激您拥有的任何 cmets。

以上是关于将 utf-8 格式的 Python 列表写入 CSV的主要内容,如果未能解决你的问题,请参考以下文章

Python:如何将列表列表写入文本文件?

Python,如何将长度不等的嵌套列表写入csv文件?

如何将列表列表写入 CSV 文件 Python?

使用 FileWriter (Java) 以 UTF-8 格式写入文件?

如何将 python 中 for 循环的输出写入 csv 格式的文件?

将数据写入excel