Leer un archivo CSV UTF8 con Python
Estoy intentando leer un archivo CSV con caracteres acentuados con Python (sólo caracteres franceses y/o españoles). Basado en la documentación de Python 2.5 para csvreader ( http://docs.python.org/library/csv.html ), se me ocurrió el siguiente código para leer el archivo CSV, ya que csvreader solo admite 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:
...
A continuación se muestra un extracto del archivo CSV que estoy intentando leer:
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
...
Aunque intento codificar/decodificar en UTF-8, sigo recibiendo la siguiente excepción:
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)
¿Cómo puedo solucionar esto?
El .encode
método se aplica a una cadena Unicode para crear una cadena de bytes; pero en su lugar lo estás llamando a una cadena de bytes... ¡al revés! Mire el codecs
módulo en la biblioteca estándar y, codecs.open
en particular, encontrará mejores soluciones generales para leer archivos de texto codificados en UTF-8. Sin embargo, para el csv
módulo en particular, necesitas pasar datos utf-8, y eso es lo que ya estás obteniendo, por lo que tu código puede ser mucho más simple:
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
PD: si resulta que sus datos de entrada NO están en utf-8, sino, por ejemplo, en ISO-8859-1, entonces necesita una "transcodificación" (si está interesado en usar utf-8 a csv
nivel de módulo) , de la forma line.decode('whateverweirdcodec').encode('utf-8')
-- pero probablemente puedas usar el nombre de tu codificación existente en la yield
línea de mi código anterior, en lugar de 'utf-8'
, como csv
en realidad estará bien con las cadenas de bytes codificadas ISO-8859-*.
Pitón 2.X
Existe una biblioteca Unicode-csv que debería resolver sus problemas, con el beneficio adicional de no tener que navegar para escribir ningún código nuevo relacionado con csv.
Aquí hay un ejemplo de su archivo Léame:
>>> 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]
é ñ
Pitón 3.X
En Python 3, esto es compatible desde el primer momento con el módulo integrado csv
. Vea este ejemplo:
import csv
with open('some.csv', newline='', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
print(row)