在Python中从CSV文件获取并显示UTF-8内容
今天我玩这个真是太有趣了。我有一个叫做 test.csv 的数据文件,它的编码是 UTF-8:
"Nguyễn", 0.500
"Trần", 0.250
"Lê", 0.250
现在我尝试用这段代码读取它,但显示出来的字符却变得很奇怪,比如变成了 Trần。
我查阅了我用的 Python 2.6 的所有文档,但还是没能让代码正常工作。网上的各种建议我也都看过,感觉都是对的,只是我没有正确地应用而已。不过好的一点是,我了解到并不是所有字体都能正确显示这些字符,这点我之前根本没想到。同时,我也学到了很多关于 Unicode 的知识,所以这段时间并没有白费。
如果有人能指出我哪里出错了,我会非常感激。
这是根据下面的请求更新后的代码,它返回了这个错误 -
Traceback (most recent call last): File "surname_generator.py", line 39, in probfamilynames = [(familyname,float(prob)) for familyname,prob in unicode_csv_reader(open(familynamelist))] File "surname_generator.py", line 27, in unicode_csv_reader for row in csv_reader: File "surname_generator.py", line 33, in utf_8_encoder yield line.encode('utf-8') UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 0: ordinal not in range(128)
from random import random
import csv
class ChooseFamilyName(object):
def __init__(self, probs):
self._total_prob = 0.
self._familyname_levels = []
for familyname, prob in probs:
self._total_prob += prob
self._familyname_levels.append((self._total_prob, familyname))
return
def pickfamilyname(self):
pickfamilyname = self._total_prob * random()
for level, familyname in self._familyname_levels:
if level >= pickfamilyname:
return familyname
print "pickfamilyname error"
return
def unicode_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs):
csv_reader = csv.reader(utf_8_encoder(unicode_csv_data),
dialect=dialect, **kwargs)
for row in csv_reader:
# decode UTF-8 back to Unicode, cell by cell:
yield [unicode(cell, 'utf-8') for cell in row]
def utf_8_encoder(unicode_csv_data):
for line in unicode_csv_data:
yield line.encode('utf-8')
familynamelist = 'familyname_vietnam.csv'
a = 0
while a < 10:
a = a + 1
probfamilynames = [(familyname,float(prob)) for familyname,prob in unicode_csv_reader(open(familynamelist))]
familynamepicker = ChooseFamilyName(probfamilynames)
print(familynamepicker.pickfamilyname())
3 个回答
在Python的文档里,有一个关于unicode_csv_reader的示例:http://docs.python.org/library/csv.html
你现在遇到的问题是,关于csv_unicode_reader的使用给你带来了误导。正如名字所示,文档也明确说明:
"""(下面的unicode_csv_reader是一个生成器,它包装了csv.reader,用来处理Unicode CSV数据(即一系列Unicode字符串)。"""
但实际上,你并没有Unicode字符串,而是UTF-8编码的普通字符串。
建议:放弃csv_unicode_reader的东西。直接把每一行当作普通的ASCII编码来处理。然后再把每一行转换成Unicode:
unicode_row = [field.decode('utf8') for field in str_row]
回到你最初的问题:
(1) 如果你想获得关于字体等方面的帮助,你需要说明你使用的平台和显示Unicode字符串的软件。
(2) 如果你想要一些不依赖于平台的方法来检查你的数据,可以看看内置的repr()函数,以及unicodedata模块中的name函数。
unicode_csv_reader(open(familynamelist))
这个代码试图把非unicode的数据(用utf-8编码的字节字符串)传给你写的一个函数,而这个函数是期待接收unicode数据的。你可以用标准库中的codecs.open来解决这个问题,但这样做有点绕:codecs会帮你把utf8转换成unicode,然后你的代码又要把unicode转换回utf8,这样做有什么意义呢?
相反,你可以定义一个更像这样的函数……:
def encoded_csv_reader_to_unicode(encoded_csv_data,
coding='utf-8',
dialect=csv.excel,
**kwargs):
csv_reader = csv.reader(encoded_csv_data,
dialect=dialect,
**kwargs)
for row in csv_reader:
yield [unicode(cell, coding) for cell in row]
然后使用 encoded_csv_reader_to_unicode(open(familynamelist))
。