I am using Python 3.2.1 and I can't import the StringIO
module. I use
io.StringIO
and it works, but I can't use it with numpy
's genfromtxt
like this:
x="1 3\n 4.5 8"
numpy.genfromtxt(io.StringIO(x))
I get the following error:
TypeError: Can't convert 'bytes' object to str implicitly
and when I write import StringIO
it says
ImportError: No module named 'StringIO'
From What’s New In Python 3.0:
.
A possibly useful method of fixing some Python 2 code to also work in Python 3 (caveat emptor):
You can use the StringIO from the six module:
In my case I have used:
In order to make examples from here work with Python 3.5.2, you can rewrite as follows :
The reason for the change may be that the content of a file is in data (bytes) which do not make text until being decoded somehow.
genfrombytes
may be a better name thangenfromtxt
.try this
from StringIO import StringIO
x="1 3\n 4.5 8"
numpy.genfromtxt(StringIO(x))
Roman Shapovalov's code should work in Python 3.x as well as Python 2.6/2.7. Here it is again with the complete example:
Output:
Explanation for Python 3.x:
numpy.genfromtxt
takes a byte stream (a file-like object interpreted as bytes instead of Unicode).io.BytesIO
takes a byte string and returns a byte stream.io.StringIO
, on the other hand, would take a Unicode string and and return a Unicode stream.x
gets assigned a string literal, which in Python 3.x is a Unicode string.encode()
takes the Unicode stringx
and makes a byte string out of it, thus givingio.BytesIO
a valid argument.The only difference for Python 2.6/2.7 is that
x
is a byte string (assumingfrom __future__ import unicode_literals
is not used), and thenencode()
takes the byte stringx
and still makes the same byte string out of it. So the result is the same.Since this is one of SO's most popular questions regarding
StringIO
, here's some more explanation on the import statements and different Python versions.Here are the classes which take a string and return a stream:
io.BytesIO
(Python 2.6, 2.7, and 3.x) - Takes a byte string. Returns a byte stream.io.StringIO
(Python 2.6, 2.7, and 3.x) - Takes a Unicode string. Returns a Unicode stream.StringIO.StringIO
(Python 2.x) - Takes a byte string or Unicode string. If byte string, returns a byte stream. If Unicode string, returns a Unicode stream.cStringIO.StringIO
(Python 2.x) - Faster version ofStringIO.StringIO
, but can't take Unicode strings which contain non-ASCII characters.Note that
StringIO.StringIO
is imported asfrom StringIO import StringIO
, then used asStringIO(...)
. Either that, or you doimport StringIO
and then useStringIO.StringIO(...)
. The module name and class name just happen to be the same. It's similar todatetime
that way.What to use, depending on your supported Python versions:
If you only support Python 3.x: Just use
io.BytesIO
orio.StringIO
depending on what kind of data you're working with.If you support both Python 2.6/2.7 and 3.x, or are trying to transition your code from 2.6/2.7 to 3.x: The easiest option is still to use
io.BytesIO
orio.StringIO
. AlthoughStringIO.StringIO
is flexible and thus seems preferred for 2.6/2.7, that flexibility could mask bugs that will manifest in 3.x. For example, I had some code which usedStringIO.StringIO
orio.StringIO
depending on Python version, but I was actually passing a byte string, so when I got around to testing it in Python 3.x it failed and had to be fixed.Another advantage of using
io.StringIO
is the support for universal newlines. If you pass the keyword argumentnewline=''
intoio.StringIO
, it will be able to split lines on any of\n
,\r\n
, or\r
. I found thatStringIO.StringIO
would trip up on\r
in particular.Note that if you import
BytesIO
orStringIO
fromsix
, you getStringIO.StringIO
in Python 2.x and the appropriate class fromio
in Python 3.x. If you agree with my previous paragraphs' assessment, this is actually one case where you should avoidsix
and just import fromio
instead.If you support Python 2.5 or lower and 3.x: You'll need
StringIO.StringIO
for 2.5 or lower, so you might as well usesix
. But realize that it's generally very difficult to support both 2.5 and 3.x, so you should consider bumping your lowest supported version to 2.6 if at all possible.