用Python读取UTF8 CSV文件
我正在尝试使用Python(只有法文和/或西class牙文字符)读取带重音字符的CSV文件。 基于csvreader( http://docs.python.org/library/csv.html )的Python 2.5文档,我想出了以下代码来读取CSV文件,因为csvreader只支持ASCII。
def unicode_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs): # csv.py doesn't do Unicode; encode temporarily as UTF-8: 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') filename = 'output.csv' reader = unicode_csv_reader(open(filename)) try: products = [] for field1, field2, field3 in reader: ...
以下是我试图读取的CSV文件的摘录:
0665000FS10120684,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Bleu 0665000FS10120689,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Gris 0665000FS10120687,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Vert ...
即使我尝试编码/解码为UTF-8,我仍然得到以下exception:
Traceback (most recent call last): File ".\Test.py", line 53, in <module> for field1, field2, field3 in reader: File ".\Test.py", line 40, in unicode_csv_reader for row in csv_reader: File ".\Test.py", line 46, in utf_8_encoder yield line.encode('utf-8', 'ignore') UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 68: ordinal not in range(128)
我该如何解决?
.encode
方法被应用到一个Unicodestring中以产生一个字节串; 但是你用一个字节串来调用它,而不是……错误的方式! 查看标准库和codecs
中的codecs
模块,特别是用于阅读UTF-8编码文本文件的更好的通用解决scheme。 但是,特别是对于csv
模块,您需要传递utf-8数据,这就是您已经获得的数据,所以您的代码可以更简单:
import csv def unicode_csv_reader(utf8_data, dialect=csv.excel, **kwargs): csv_reader = csv.reader(utf8_data, dialect=dialect, **kwargs) for row in csv_reader: yield [unicode(cell, 'utf-8') for cell in row] filename = 'da.csv' reader = unicode_csv_reader(open(filename)) for field1, field2, field3 in reader: print field1, field2, field3
PS:如果你的input数据不在utf-8中,但是在ISO-8859-1中,那么你需要一个“代码转换”(如果你想在csv
模块级使用utf-8) )的formsline.decode('whateverweirdcodec').encode('utf-8')
– 但可能你可以在我的代码上面的yield
行中使用你现有编码的名字,而不是'utf-8'
,因为在ISO-8859- *编码的字节串中csv
实际上会很好。
Python 2.X
有一个unicode-csv库应该可以解决你的问题,不用写任何新的csv相关的代码。
以下是自述文件中的一个示例:
>>> import unicodecsv >>> from cStringIO import StringIO >>> f = StringIO() >>> w = unicodecsv.writer(f, encoding='utf-8') >>> w.writerow((u'é', u'ñ')) >>> f.seek(0) >>> r = unicodecsv.reader(f, encoding='utf-8') >>> row = r.next() >>> print row[0], row[1] é ñ
Python 3.X
在python 3中,内置的csv
模块支持开箱即用。 看到这个例子:
import csv with open('some.csv', newline='', encoding='utf-8') as f: reader = csv.reader(f) for row in reader: print(row)
另外签出这个职位的答案: https : //stackoverflow.com/a/9347871/1338557
它build议使用名为ucsv.py的库。 用于解决Python 2.7编码问题(utf-8)的CSV短而简单的replace。 还提供对csv.DictReader的支持
编辑 :添加我使用的示例代码:
import ucsv as csv #Read CSV file containing the right tags to produce fileObj = open('awol_title_strings.csv', 'rb') dictReader = csv.DictReader(fileObj, fieldnames = ['titles', 'tags'], delimiter = ',', quotechar = '"') #Build a dictionary from the CSV file-> {<string>:<tags to produce>} titleStringsDict = dict() for row in dictReader: titleStringsDict.update({unicode(row['titles']):unicode(row['tags'])})
到python 2.6的帮助页面的链接是相同的,据我所知,自2.5以来没有改变csv模块(除了bug修复)。 这里是没有任何编码/解码的代码(文件da.csv包含与variables数据相同的数据 )。 我假设您的文件应该没有任何转换正确读取。
test.py:
## -*- coding: utf-8 -*- # # NOTE: this first line is important for the version b) read from a string(unicode) variable # import csv data = \ """0665000FS10120684,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Bleu 0665000FS10120689,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Gris 0665000FS10120687,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Vert""" # a) read from a file print 'reading from a file:' for (f1, f2, f3) in csv.reader(open('da.csv'), dialect=csv.excel): print (f1, f2, f3) # b) read from a string(unicode) variable print 'reading from a list of strings:' reader = csv.reader(data.split('\n'), dialect=csv.excel) for (f1, f2, f3) in reader: print (f1, f2, f3)
da.csv:
0665000FS10120684,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Bleu 0665000FS10120689,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Gris 0665000FS10120687,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Vert
查看Latin-1
unicode表 ,我看到字符代码00E9
“ LATIN小 00E9
E急性 ”。 这是样本数据中的重音字符。 Python
中的一个简单testing表明, UTF-8
编码与unicode(几乎是UTF-16
)编码不同。
>>> u'\u00e9' u'\xe9' >>> u'\u00e9'.encode('utf-8') '\xc3\xa9' >>>
我build议你在调用特殊的unicode_csv_reader()
之前尝试encode("UTF-8")
unicode数据。 简单地从文件中读取数据可能会隐藏编码,因此请检查实际的字符值。
使用codecs.open
,Alex Martellibuild议certificate对我有用。
import codecs delimiter = ';' reader = codecs.open("your_filename.csv", 'r', encoding='utf-8') for line in reader: row = line.split(delimiter) # do something with your row ...