在Python中从CSV文件获取并显示UTF-8内容

0 投票
3 回答
705 浏览
提问于 2025-04-15 15:02

今天我玩这个真是太有趣了。我有一个叫做 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 个回答

-2

在Python的文档里,有一个关于unicode_csv_reader的示例:http://docs.python.org/library/csv.html

0

你现在遇到的问题是,关于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函数。

1

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))

撰写回答