Python: escriba Unicode a CSV usando UnicodeWriter

Los documentos de Python tienen el siguiente ejemplo de código al escribir unicode en un archivo csv. Creo que se ha mencionado que esta es la forma de hacerlo ya que el módulo csv no puede manejar cadenas Unicode.

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) 

Estoy escribiendo más de un archivo y, para mantenerlo simple, solo he puesto la sección de mi código para demostrar cómo uso la clase anterior en mi código:

 def write(self): """ Outputs the dataset to a csv. """ f = codecs.open(self.filename, 'a') writer = UnicodeWriter(f) #with open(self.filename, 'a', encoding='utf-8') as f: if self.headers and not self.written: writer.writerow(self.headers) self.written = True for record in self.records[self.last_written:]: print record writer.writerow(record) self.last_written = len(self.records) f.close() 

Este es un método dentro de un conjunto de datos de recostackción de clase que prepara el conjunto de datos antes de escribir en csv, anteriormente estaba usando writer = csv.writer(f) pero debido a errores de códec, cambio mi código para usar la clase `UnicodeWriter.

Pero mi problema es que cuando abro el archivo csv, obtengo lo siguiente:

 some_header B,r,ë,k,ò,w,n,i,k,_,b,s B,r,ë,k,ò,w,n,i,k,_,c,s B,r,ë,k,ò,w,n,i,k,_,c,s,b B,r,ë,k,ò,w,n,i,k,_,d,e B,r,ë,k,ò,w,n,i,k,_,d,e,-,1 B,r,ë,k,ò,w,n,i,k,_,d,e,-,2 B,r,ë,k,ò,w,n,i,k,_,d,e,-,3 B,r,ë,k,ò,w,n,i,k,_,d,e,-,4 B,r,ë,k,ò,w,n,i,k,_,d,e,-,5 B,r,ë,k,ò,w,n,i,k,_,d,e,-,M B,r,ë,k,ò,w,n,i,k,_,e,n B,r,ë,k,ò,w,n,i,k,_,e,n,-,1 B,r,ë,k,ò,w,n,i,k,_,e,n,-,2 

Donde estas filas deberían ser en realidad algo así como Brëkòwnik_de-1 no estoy realmente qué está sucediendo.

Para dar una idea básica de cómo se han generado los datos, agregaría la siguiente línea: title = unicode(row_page_title['page_title'], 'utf-8')

Este síntoma apunta a algo como alimentar una cadena en una función / método que está esperando una lista o tupla.

El método de writerows es esperar una lista de listas y la writerow espera una lista (o tupla) que contenga los valores de campo. Ya que le está dando una cadena y una cadena puede imitar una lista de caracteres cuando la itera, obtiene un CSV con un carácter en cada columna.

Si su CSV tiene solo una columna, debe usar writer.writerow([data]) lugar de writer.writerow(data) . Algunos pueden preguntarse si realmente necesita el módulo csv si solo tiene una columna, pero el módulo csv manejará cosas como un registro que contiene cosas divertidas (CR / LF y otras), así que sí, es una buena idea.