Cómo escribir UTF-8 en un archivo CSV

83

Estoy tratando de crear un archivo de texto en formato csv a partir de PyQt4 QTableWidget. Quiero escribir el texto con codificación UTF-8 porque contiene caracteres especiales. Yo uso el siguiente código:

import codecs
...
myfile = codecs.open(filename, 'w','utf-8')
...
f = result.table.item(i,c).text()
myfile.write(f+";")

Funciona hasta que la celda contiene un carácter especial. Probé también con

myfile = open(filename, 'w')
...
f = unicode(result.table.item(i,c).text(), "utf-8")

Pero también se detiene cuando aparece un personaje especial. No tengo idea de lo que estoy haciendo mal.

Martín
fuente
"salso tops"? Qué significa eso? ¿Qué error obtienes? ¿Cuál es tu aportación?
La entrada es un QTableWidgetItem pyqt4. El problema es que no obtengo ningún error porque el script se ejecuta como un complemento.
Martin
Luego intente reproducir el problema fuera de QT.
Encontré la solución. Tuve que escribirmyfile.write(u"%s"&f+";")
Martin
Consulte también: ¿Cómo leo y escribo archivos CSV con Python?
Martin Thoma

Respuestas:

106

Desde su shell ejecutar:

pip2 install unicodecsv

Y (a diferencia de la pregunta original) suponiendo que está utilizando Python construido en el csvmódulo, a su vez,
import csven
import unicodecsv as csvsu código.

kqw
fuente
29
No funcionó simplemente reemplazando la importación, también tuve que agregar la codificación al crear el escritor: writer = csv.writer(out, dialect='excel', encoding='utf-8')y crear el controlador de archivos con open(..., no codecs.open(... .
Suzana
4
Probé todas las sugerencias en StackOverflow y solo esta funciona para mí.
Charles Chow
90

Es muy simple para Python 3.x ( docs ).

import csv

with open('output_file_name', 'w', newline='', encoding='utf-8') as csv_file:
    writer = csv.writer(csv_file, delimiter=';')
    writer.writerow('my_utf8_string')

Para Python 2.x, mira aquí .

Zanon
fuente
1
¿y si el contenido de writerowno es un utf-8? ¿Funcionará?
CKM
1
Excelente, sin necesidad de instalaciones de pip de terceros.
Vaibhav Vishal
3

Para mí, la UnicodeWriterclase de la documentación del módulo CSV de Python 2 realmente no funcionó ya que rompe la csv.writer.write_row()interfaz.

Por ejemplo:

csv_writer = csv.writer(csv_file)
row = ['The meaning', 42]
csv_writer.writerow(row)

funciona, mientras que:

csv_writer = UnicodeWriter(csv_file)
row = ['The meaning', 42]
csv_writer.writerow(row)

arrojará AttributeError: 'int' object has no attribute 'encode'.

Como UnicodeWriterobviamente espera que todos los valores de columna sean cadenas, podemos convertir los valores nosotros mismos y simplemente usar el módulo CSV predeterminado:

def to_utf8(lst):
    return [unicode(elem).encode('utf-8') for elem in lst]

...
csv_writer.writerow(to_utf8(row))

O incluso podemos modificar csv_writer para agregar una write_utf8_rowfunción; el ejercicio queda en manos del lector.

Bojan Bogdanovic
fuente
2

Los ejemplos de la documentación de Python muestran cómo escribir archivos CSV Unicode: http://docs.python.org/2/library/csv.html#examples

(no se puede copiar el código aquí porque está protegido por derechos de autor)

Aaron Digulla
fuente
1
Gracias por el enlace. Fue de gran ayuda. Para mi conocimiento, incluso si ha publicado el enlace, no puede copiar y pegar el código aquí. (+1 por poseer los derechos de autor)
Mutant
1
@Mutant: El código no es como los artículos científicos. El código está protegido por derechos de autor. Si bien estoy 99,999% seguro de que los propietarios de Python no demandarían a SO por copiar su código, no tenía ganas de leer su extensa licencia para averiguar si está permitido o no. Además, es bueno recordarle a la gente de vez en cuando que "¡Puedo verlo en mi monitor"! = "Puedo hacer lo que quiera con él" :-)
Aaron Digulla
1
Gracias por el recordatorio. Desafortunadamente, el mundo en el que vivimos se volvió tan (irrazonablemente) rápido y descuidado donde la información fluye más rápido de lo que uno puede imaginar, requiere un recordatorio una vez y mientras está en la restricción que importa. Gracias por eso :)
Mutant
2
El enlace de documentos es semi-útil (los ejemplos son mejores), pero el argumento de "copyright" aquí es exagerado y estúpido. Python es explícitamente de código abierto ( v2 v3 ). La licencia es clara: "licencia mundial libre de regalías para reproducir, analizar, probar, realizar y / o exhibir públicamente, preparar trabajos derivados, distribuir ... [etc., etc.]" Incluso la simple frase en el parte superior de la página, "compatible con GPL" debería brindarle comodidad. Comparta material de código abierto. Incluso modifíquelo si lo desea. Es de código abierto por una razón.
alttag
@alttag Copiar o usar código GPLd en un proyecto significa que todo el resto del código en el mismo proyecto ahora también está bajo GPL. Como no soy un abogado de derechos de autor, no sé qué significa eso con respecto al código publicado en un sitio web.
Aaron Digulla
0

Para python2 , puede usar este código antes. csv_writer.writerows(rows)
Este código NO convertirá enteros en cadenas utf-8

def encode_rows_to_utf8 (filas):
    encoded_rows = []
    para fila en filas:
        encoded_row = []
        por valor en fila:
            if isinstance (valor, cadena base):
                valor = unicode (valor) .encode ("utf-8")
            encoded_row.append (valor)
        encoded_rows.append (encoded_row)
    return encoded_rows
pymen
fuente
-1

Un truco muy simple es usar la importación json en lugar de csv. Por ejemplo, en lugar de csv.writer, haga lo siguiente:

    fd = codecs.open(tempfilename, 'wb', 'utf-8')  
    for c in whatever :
        fd.write( json.dumps(c) [1:-1] )   # json dumps writes ["a",..]
        fd.write('\n')
    fd.close()

Básicamente, dada la lista de campos en el orden correcto, la cadena con formato json es idéntica a una línea csv excepto por [y] al principio y al final respectivamente. Y json parece ser robusto para utf-8 en python 2. *

vpathak
fuente