Estou a utilizar o Python 3.2.1 e posso'não importar o módulo StringIO
. Eu utilizo o
"io.StringIO" e funciona, mas não posso'não posso utilizá-lo com numpy
's genfromtxt
como este:
x="1 3\n 4.5 8"
numpy.genfromtxt(io.StringIO(x))
Recebo o seguinte erro:
TypeError: Can't convert 'bytes' object to str implicitly
e quando escrevo "StringIO importado", diz
ImportError: No module named 'StringIO'
quando escrevo StringIO de importação, diz que não existe tal módulo.
De O que há de novo em Python 3.0:
os módulos
StringIO
ecStringIO
desapareceram. Em vez disso, importar oio'. modifique e utilize
io.StringIOou
io.BytesIO` para texto e dados respectivamente.
.
Um método possivelmente útil de fixar algum código Python 2 para trabalhar também em Python 3 (caveat emptor):
try:
from StringIO import StringIO ## for Python 2
except ImportError:
from io import StringIO ## for Python 3
Note: Este exemplo pode ser tangencial à questão principal da pergunta e é incluído apenas como algo a considerar quando se trata genericamente do módulo 'StringIO' em falta. Para uma solução mais directa, a mensagem 'TypeError': Can't convert 'bytes' object to stricly`, ver esta resposta.
No meu caso, já usei:
from io import StringIO
Em Python 3 numpy.genfromtxt
espera um fluxo de bytes. Utilize o seguinte:
numpy.genfromtxt(io.BytesIO(x.encode()))
Obrigado OP pela sua pergunta, e Roman pela sua resposta. Tive de procurar um pouco para encontrar isto; Espero que o seguinte ajude os outros.
**Python 2.7***
Veja: 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)
"""
<type 'str'>
"""
print '\n', np.genfromtxt(StringIO(data), delimiter=",", dtype="|S3", autostrip=True)
"""
[['1' 'abc' '2']
['3' 'xxx' '4']]
"""
print '\n', type(data)
"""
<type 'str'>
"""
print '\n', np.genfromtxt(StringIO(data), delimiter=",", autostrip=True)
"""
[[ 1. nan 2.]
[ 3. nan 4.]]
"""
Píton 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))
"""
<class 'str'>
"""
#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.]]
"""
Ajunto:
dtype="|Sx", onde x = qualquer um de { 1, 2, 3, ...}:
https://stackoverflow.com/questions/14790130/dtypes-difference-between-s1-and-s2-in-python
"As cordas |S1 e |S2 são descritores de tipo de dados; a primeira significa que a matriz contém cordas de comprimento 1, a segunda de comprimento 2. ..."
Você pode usar o [StringIO][1] a partir do módulo [seis][2]:
import six
import numpy
x = "1 3\n 4.5 8"
numpy.genfromtxt(six.StringIO(x))
[1]: https://pythonhosted.org/six/#six.StringIO [2]: https://pythonhosted.org/six/
O código Roman Shapovalov's deve funcionar em Python 3.x bem como Python 2.6/2.7. Aqui está novamente com o exemplo completo:
import io
import numpy
x = "1 3\n 4.5 8"
numpy.genfromtxt(io.BytesIO(x.encode()))
Saída:
array([[ 1. , 3. ],
[ 4.5, 8. ]])
Explicação para Python 3.x:
numpy.genfromtxt
toma um fluxo de bytes (um objeto semelhante a um arquivo interpretado como bytes ao invés de Unicode).io.BytesIO
pega uma string de bytes e retorna um fluxo de bytes.
O io.StringIO
, por outro lado, pega uma string Unicode e retorna um fluxo Unicode.x
recebe uma string literal, que em Python 3.x é uma string Unicode.encode()`` pega a string Unicode
xe faz uma string de bytes fora dela, dando assim ao
io.BytesIO` um argumento válido.A única diferença para Python 2.6/2.7 é que x
é uma string de byte (assumindo que from __future__ import unicode_literals
não é utilizado), e então encode()
pega a string de byte x
e ainda faz a mesma string de byte fora dela.
Então o resultado é o mesmo.
Como esta é uma das questões mais populares da SO's sobre o StringIO
, aqui's mais algumas explicações sobre as declarações de importação e diferentes versões Python.
Aqui estão as classes que pegam uma string e retornam um stream:
io.BytesIO
][1] (Python 2.6, 2.7, e 3.x) - Toma uma string de byte.
Retorna um fluxo de bytes.io.StringIO
][2] (Python 2.6, 2.7, e 3.x) - Toma uma string Unicode.
Retorna um fluxo Unicode.StringIO.StringIO
][3] (Python 2.x) - Toma uma string de byte ou string Unicode.
Se string de byte, retorna um fluxo de byte.
Se string Unicode, retorna um fluxo Unicode.cStringIO.StringIO
][4] (Python 2.x) - Versão mais rápida de StringIO.StringIO
, mas não pode'não aceita strings Unicode que contenham caracteres não-ASCII.Note que StringIO.StringIO
é importado como de StringIO import StringIO
, e depois utilizado como StringIO(...)
.
Ou isso, ou você faz importar StringIO
e depois utiliza StringIO.StringIO(...)
.
O nome do módulo e o nome da classe são os mesmos.
It's similar a datetime
dessa forma.
O que utilizar, dependendo das suas versões Python suportadas:
Se você só suporta Python 3.x: Basta utilizar io.BytesIO
ou io.StringIO
, dependendo do tipo de dados com que você'está trabalhando.
Se você suporta tanto o Python 2.6/2.7 como o 3.x, ou está tentando fazer a transição do seu código do 2.6/2.7 para o 3.x: A opção mais fácil ainda é utilizar o io.BytesIO
ou io.StringIO
.
Embora o io.StringIO.StringIO
seja flexível e assim pareça preferido para o 2.6/2.7, essa flexibilidade pode mascarar bugs que se manifestarão no 3.x.
Por exemplo, eu tinha algum código que utilizava StringIO.StringIO
ou io.StringIO
dependendo da versão Python, mas na verdade eu estava passando uma byte string, então quando eu cheguei a testá-lo em Python 3.x ele falhou e teve que ser corrigido.
Outra vantagem de utilizar o io.StringIO
é o suporte a novas linhas universais.
Se você passar o argumento da palavra-chave newline=''
no io.StringIO
, ele será capaz de dividir linhas em qualquer um dos \n
, \r\n
, ou \r
.
Descobri que o io.StringIO.StringIO
iria tropeçar no \r
em particular.
Note que se você importar BytesIO
ou StringIO
de [`six
][5], você recebe StringIO.StringIO
em Python 2.x e a classe apropriada de io
em Python 3.x.
Se você concordar com os meus parágrafos anteriores'
este é na verdade um caso em que você deve evitar o six
e apenas importar do io
em vez disso.
Se você suporta Python 2.5 ou inferior e 3.x: Você'vai precisar do StringIO.StringIO
para 2.5 ou inferior, então você pode também usar o six
.
Mas perceba que é geralmente muito difícil suportar tanto o 2.5 quanto o 3.x, então você deve considerar a possibilidade de aumentar sua versão mais baixa suportada para 2.6, se possível.
[1]: https://docs.python.org/3/library/io.html#binary-i-o [2]: https://docs.python.org/3/library/io.html#text-i-o [3]: https://docs.python.org/2/library/stringio.html# [4]: https://docs.python.org/2/library/stringio.html#module-cStringIO [5]: https://pythonhosted.org/six/
A fim de fazer exemplos a partir de [aqui][1] trabalhar com Python 3.5.2, você pode reescrever da seguinte forma :
import io
data =io.BytesIO(b"1, 2, 3\n4, 5, 6")
import numpy
numpy.genfromtxt(data, delimiter=",")
A razão para a mudança pode ser que o conteúdo de um arquivo esteja em dados (bytes) que não fazem texto até ser decodificado de alguma forma. O 'genfrombytes' pode ser um nome melhor do que 'genfromtxt'.
[1]: https://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html