Cómo puedo usar io.StringIO () con el módulo csv?


Traté de hacer backport de un programa Python 3 a la versión 2.7, y estoy atascado con un extraño problema:

>>> import io
>>> import csv
>>> output = io.StringIO()
>>> output.write("Hello!")            # Fail: io.StringIO expects Unicode
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unicode argument expected, got 'str'
>>> output.write(u"Hello!")           # This works as expected.
6L
>>> writer = csv.writer(output)       # Now let's try this with the csv module:
>>> csvdata = [u"Hello", u"Goodbye"]  # Look ma, all Unicode! (?)
>>> writer.writerow(csvdata)          # Sadly, no.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unicode argument expected, got 'str'

Según los documentos, io.StringIO() devuelve un flujo en memoria para texto Unicode. Funciona correctamente cuando intento alimentarlo manualmente con una cadena Unicode. ¿Por qué falla en conjunto con el módulo csv, incluso si todas las cadenas que se escriben son cadenas Unicode? ¿De dónde viene el str que causa la Excepción?

(Sé que puedo usar StringIO.StringIO() en su lugar, pero me pregunto qué hay de malo con io.StringIO() en este escenario)

Author: Tim Pietzcker, 2012-10-29

4 answers

El módulo Python 2.7 csv no admite entrada Unicode: consulte la nota al principio de la documentación.

Parece que tendrás que codificar las cadenas Unicode a cadenas de bytes, y usar io.BytesIO, en lugar de io.StringIO.

La sección examples de la documentación incluye ejemplos para las clases UnicodeReader y UnicodeWriter wrapper (gracias a @AlexeyKachayev por el puntero).

 40
Author: Pedro Romano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-29 11:04:46

Utilice StringIO.StringIO ().

Http://docs.python.org/library/io.html#io.StringIO

Http://docs.python.org/library/stringio.html

io.StringIO es una clase. Maneja Unicode. Refleja la estructura preferida de la biblioteca Python 3.

StringIO.StringIO es una clase. Maneja cuerdas. Refleja la estructura heredada de la biblioteca Python 2.

 23
Author: ernest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-08 08:56:05

Encontré esto cuando traté de servir un archivo CSV a través de Flask directamente sin crear el archivo CSV en el sistema de archivos. Esto funciona:

import io
import csv

data = [[u'cell one', u'cell two'], [u'cell three', u'cell four']]

output = io.BytesIO()
writer = csv.writer(output, delimiter=',')
writer.writerows(data)
your_csv_string = output.getvalue()

Véase también

 5
Author: Martin Thoma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-10 08:34:06

De la documentación csv:

El módulo csv no admite directamente la lectura y escritura Unicode, pero es 8-bit-limpio excepto para algunos problemas con ASCII NUL caracter. Así que usted puede escribir funciones o clases que manejan el codificación y decodificación para usted, siempre y cuando evite codificaciones como UTF-16 que usan NULs. Se recomienda UTF-8.

Usted puede encontrar ejemplo de UnicodeReader, UnicodeWriter aquí http://docs.python.org/2/library/csv.html

 4
Author: Alexey Kachayev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-29 11:00:55