StringIO en Python3

Estoy usando Python 3.2.1 y no puedo importar el módulo StringIO . Uso io.StringIO y funciona, pero no puedo usarlo con el numpy de genfromtxt como este:

 x="1 3\n 4.5 8" numpy.genfromtxt(io.StringIO(x)) 

Obtuve el siguiente error:

 TypeError: Can't convert 'bytes' object to str implicitly 

y cuando escribo import StringIO dice

 ImportError: No module named 'StringIO' 

Cuando escribo Importar StringIO dice que no hay tal módulo.

De lo nuevo en Python 3.0 :

Los módulos StringIO y cStringIO se han ido. En su lugar, importe el módulo io y use io.StringIO o io.BytesIO para texto y datos respectivamente.

.


Un método posiblemente útil para corregir algunos códigos Python 2 para que también funcionen en Python 3 (caveat emptor):

 try: from StringIO import StringIO except ImportError: from io import StringIO 

Nota: Este ejemplo puede ser tangencial a la cuestión principal de la pregunta y se incluye solo como algo a tener en cuenta al abordar de manera genérica el módulo StringIO faltante. Para una solución más directa, el mensaje TypeError: Can't convert 'bytes' object to str implicitly , vea esta respuesta .

En mi caso he utilizado:

 from io import StringIO 

En Python 3, numpy.genfromtxt espera un flujo de bytes. Usa lo siguiente:

 numpy.genfromtxt(io.BytesIO(x.encode())) 

Gracias OP por tu pregunta, y Roman por tu respuesta. Tuve que buscar un poco para encontrar esto; Espero que lo siguiente ayude a otros.

Python 2.7

Consulte: https://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html

 import numpy as np from StringIO import StringIO data = "1, abc , 2\n 3, xxx, 4" print type(data) """  """ print '\n', np.genfromtxt(StringIO(data), delimiter=",", dtype="|S3", autostrip=True) """ [['1' 'abc' '2'] ['3' 'xxx' '4']] """ print '\n', type(data) """  """ print '\n', np.genfromtxt(StringIO(data), delimiter=",", autostrip=True) """ [[ 1. nan 2.] [ 3. nan 4.]] """ 

Python 3.5:

 import numpy as np from io import StringIO import io data = "1, abc , 2\n 3, xxx, 4" #print(data) """ 1, abc , 2 3, xxx, 4 """ #print(type(data)) """  """ #np.genfromtxt(StringIO(data), delimiter=",", autostrip=True) # TypeError: Can't convert 'bytes' object to str implicitly print('\n') print(np.genfromtxt(io.BytesIO(data.encode()), delimiter=",", dtype="|S3", autostrip=True)) """ [[b'1' b'abc' b'2'] [b'3' b'xxx' b'4']] """ print('\n') print(np.genfromtxt(io.BytesIO(data.encode()), delimiter=",", autostrip=True)) """ [[ 1. nan 2.] [ 3. nan 4.]] """ 

Aparte:

dtype = “| Sx”, donde x = cualquiera de {1, 2, 3, …}:

dtypes. Diferencia entre S1 y S2 en Python

“Las cadenas | S1 y | S2 son descriptores de tipo de datos; el primero significa que la matriz contiene cadenas de longitud 1, la segunda de longitud 2. …”

Puedes usar el StringIO desde el módulo seis :

 import six import numpy x = "1 3\n 4.5 8" numpy.genfromtxt(six.StringIO(x)) 

Para que los ejemplos de aquí funcionen con Python 3.5.2, puede volver a escribir de la siguiente manera:

 import io data =io.BytesIO(b"1, 2, 3\n4, 5, 6") import numpy numpy.genfromtxt(data, delimiter=",") 

El motivo del cambio puede ser que el contenido de un archivo está en datos (bytes) que no forman texto hasta que se decodifican de alguna manera. genfrombytes puede ser un nombre mejor que genfromtxt .

El código de Roman Shapovalov debería funcionar en Python 3.x así como en Python 2.6 / 2.7. Aquí está de nuevo con el ejemplo completo:

 import io import numpy x = "1 3\n 4.5 8" numpy.genfromtxt(io.BytesIO(x.encode())) 

Salida:

 array([[ 1. , 3. ], [ 4.5, 8. ]]) 

Explicación para Python 3.x:

  • numpy.genfromtxt toma un flujo de bytes (un objeto similar a un archivo interpretado como bytes en lugar de Unicode).
  • io.BytesIO toma una cadena de bytes y devuelve un flujo de bytes. io.StringIO , por otro lado, tomaría una cadena Unicode y devolvería una secuencia Unicode.
  • x se le asigna una cadena literal, que en Python 3.x es una cadena Unicode.
  • encode() toma la cadena x Unicode y la convierte en una cadena de bytes, lo que le da a io.BytesIO un argumento válido.

La única diferencia para Python 2.6 / 2.7 es que x es una cadena de bytes (asumiendo que from __future__ import unicode_literals no se usa from __future__ import unicode_literals ), y luego encode() toma la cadena de bytes x y aún hace la misma cadena de bytes. Entonces el resultado es el mismo.


Ya que esta es una de las preguntas más populares de SO con respecto a StringIO , aquí hay algunas explicaciones más sobre las declaraciones de importación y las diferentes versiones de Python.

Aquí están las clases que toman una cadena y devuelven una secuencia:

  • io.BytesIO (Python 2.6, 2.7 y 3.x): toma una cadena de bytes. Devuelve un flujo de bytes.
  • io.StringIO (Python 2.6, 2.7 y 3.x) – Toma una cadena Unicode. Devuelve una secuencia Unicode.
  • StringIO.StringIO (Python 2.x): toma una cadena de bytes o una cadena Unicode. Si la cadena de bytes, devuelve un flujo de bytes. Si la cadena de Unicode, devuelve una secuencia de Unicode.
  • cStringIO.StringIO (Python 2.x): versión más rápida de StringIO.StringIO , pero no puede tomar cadenas Unicode que contengan caracteres no ASCII.

Tenga en cuenta que StringIO.StringIO se importa from StringIO import StringIO , luego se usa como StringIO(...) . O eso, o si import StringIO y luego usas StringIO.StringIO(...) . El nombre del módulo y el nombre de la clase son los mismos. Es similar a datetime esa manera.

Qué usar, dependiendo de las versiones de Python compatibles:

  • Si solo es compatible con Python 3.x: simplemente use io.BytesIO o io.StringIO según el tipo de datos con los que esté trabajando.

  • Si es compatible con Python 2.6 / 2.7 y 3.x, o está intentando hacer una transición de su código de 2.6 / 2.7 a 3.x: la opción más sencilla es utilizar io.BytesIO o io.StringIO . Aunque StringIO.StringIO es flexible y por lo tanto parece preferible para 2.6 / 2.7, esa flexibilidad podría enmascarar errores que se manifestarán en 3.x. Por ejemplo, tenía un código que usaba StringIO.StringIO o io.StringIO dependiendo de la versión de Python, pero en realidad estaba pasando una cadena de bytes, así que cuando io.StringIO en Python 3.x, falló y tuve que corregirlo. .

    Otra ventaja de usar io.StringIO es el soporte para nuevas líneas universales. Si pasa el argumento de la palabra clave newline='' a io.StringIO , podrá dividir líneas en cualquiera de \n , \r\n o \r . Encontré que StringIO.StringIO se dispararía en particular en particular.

    Tenga en cuenta que si importa BytesIO o StringIO desde six , obtendrá StringIO.StringIO en Python 2.xy la clase apropiada de io en Python 3.x. Si está de acuerdo con la evaluación de mis párrafos anteriores, este es realmente un caso en el que debe evitar six y simplemente importar desde io lugar.

  • Si es compatible con Python 2.5 o inferior y 3.x: necesitará StringIO.StringIO para 2.5 o inferior, por lo que también puede utilizar six . Pero tenga en cuenta que, en general, es muy difícil admitir tanto 2.5 como 3.x, por lo que debería considerar subir su versión más baja compatible a 2.6 si es posible.

prueba esto

desde StringIO import StringIO

x = “1 3 \ n 4.5 8”

numpy.genfromtxt (StringIO (x))