Crear un archivo csv utf-8 en Python

No puedo crear un archivo csv utf-8 en Python.

Estoy tratando de leer sus documentos, y en la sección de ejemplos , dice:

Para todas las demás codificaciones, se pueden usar las siguientes clases de UnicodeReader y UnicodeWriter. Toman un parámetro de encoding adicional en su constructor y se aseguran de que los datos pasen al lector o escritor real codificado como UTF-8:

De acuerdo. Así que tengo este código:

values = (unicode("Ñ", "utf-8"), unicode("é", "utf-8")) f = codecs.open('eggs.csv', 'w', encoding="utf-8") writer = UnicodeWriter(f) writer.writerow(values) 

Y sigo recibiendo este error:

 line 159, in writerow self.stream.write(data) File "/usr/lib/python2.6/codecs.py", line 686, in write return self.writer.write(data) File "/usr/lib/python2.6/codecs.py", line 351, in write data, consumed = self.encode(object, self.errors) UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 22: ordinal not in range(128) 

¿Puede alguien, por favor, darme una luz para que pueda entender qué demonios estoy haciendo mal, ya que configuro toda la encoding en todas partes antes de llamar a la clase UnicodeWriter?

 class UnicodeWriter: """ A CSV writer which will write rows to CSV file "f", which is encoded in the given encoding. """ def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds): # Redirect output to a queue self.queue = cStringIO.StringIO() self.writer = csv.writer(self.queue, dialect=dialect, **kwds) self.stream = f self.encoder = codecs.getincrementalencoder(encoding)() def writerow(self, row): self.writer.writerow([s.encode("utf-8") for s in row]) # Fetch UTF-8 output from the queue ... data = self.queue.getvalue() data = data.decode("utf-8") # ... and reencode it into the target encoding data = self.encoder.encode(data) # write to the target stream self.stream.write(data) # empty queue self.queue.truncate(0) def writerows(self, rows): for row in rows: self.writerow(row) 

No tienes que usar codecs.open ; UnicodeWriter toma la entrada de Unicode y se encarga de codificar todo en UTF-8. Cuando UnicodeWriter escribe en el identificador de archivo que le pasó, todo está ya en encoding UTF-8 (por lo tanto, funciona con un archivo normal que abrió con open ).

Al usar codecs.open , esencialmente convierte sus objetos Unicode en cadenas UTF-8 en UnicodeWriter , luego intenta volver a codificar estas cadenas en UTF-8 nuevamente como si estas cadenas contuvieran cadenas Unicode, que obviamente fallan.

Tal como lo has descubierto, funciona si utilizas plano abierto.

La razón de esto es que intentaste codificar UTF-8 dos veces. Una vez en

 f = codecs.open('eggs.csv', 'w', encoding="utf-8") 

y luego más tarde en UnicodeWriter.writeRow

 # ... and reencode it into the target encoding data = self.encoder.encode(data) 

Para verificar que esto funciona, use su código original y comience esa línea.

Greetz

Me encontré con el desafío csv / unicode hace un tiempo y lo lancé a bitbucket: http://bitbucket.org/famousactress/dude_csv .. podría funcionar para usted, si sus necesidades son simples 🙂

No es necesario “codificar dos veces” todo.

Su aplicación debería funcionar completamente en Unicode.

Realice la encoding solo en los codecs.open para escribir bytes UTF-8 en un archivo externo. No haga ninguna otra encoding dentro de su aplicación.