python3 - ¿Cómo puedo usar io.StringIO() con el módulo csv?
stringio ruby (4)
Traté de respaldar un programa de Python 3 con 2.7, y tengo 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 una secuencia en memoria para texto Unicode. Funciona correctamente cuando intento alimentarlo manualmente con una cadena Unicode. ¿Por qué falla junto 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()
, pero me pregunto qué le pasa a io.StringIO()
en este escenario)
De la documentación de csv
:
El módulo csv no admite directamente la lectura y escritura de Unicode, pero es un ahorro de 8 bits para algunos problemas con los caracteres ASCII NUL. De modo que puede escribir funciones o clases que manejen la codificación y decodificación siempre que evite codificaciones como UTF-16 que usan NUL. UTF-8 es recomendado.
Puede encontrar ejemplos de UnicodeReader
, UnicodeWriter
aquí http://docs.python.org/2/library/csv.html
El módulo Python 2.7 csv
no es compatible con la entrada Unicode: vea la nota al principio de la documentación .
Parece que tendrá que codificar las cadenas Unicode para cadenas de bytes y usar io.BytesIO
, en lugar de io.StringIO
.
La sección de examples de la documentación incluye ejemplos para las clases de contenedor UnicodeReader
y UnicodeWriter
(gracias @AlexeyKachayev para el puntero).
Encontré esto cuando intenté publicar 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()
Ver también
- Más sobre CSV
- La parte del frasco
- Algunas notas sobre Strings / Unicode
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 cadenas. Refleja la estructura de la biblioteca heredada de Python 2.