I'm trying to migrate a python 2 project to be python 3 compatible, and got hung up when it was harder than expected to replace a StringIO.StringIO
with io.BytesIO
. After a lot of debugging I think the problem comes down to this difference in behaviors:
Using StringIO.StringIO
:
>>> sys.executable
'/Users/michael/.pyenv/versions/2.7.17/bin/python'
>>> s = StringIO.StringIO()
>>> s.truncate(0)
>>> s.write('a')
>>> s.flush()
>>> s.seek(0)
>>> s.read()
'a'
>>> s.truncate(0)
>>> s.write('a')
>>> s.flush()
>>> s.seek(0)
>>> s.read()
'a'
Using io.BytesIO
:
>>> sys.executable
'/Users/michael/.pyenv/versions/2.7.17/bin/python'
>>> b = io.BytesIO()
>>> b.truncate(0)
0L
>>> b.write('a')
1L
>>> b.flush()
>>> b.seek(0)
0L
>>> b.read()
'a'
>>> b.truncate(0)
0L
>>> b.write('a')
1L
>>> b.flush()
>>> b.seek(0)
0L
>>> b.read()
'\x00a'
So you can see the second time through, truncating and flushing the buffer the io.BytesIO
object gets a null byte at the beginning, but the StringIO.StringIO one does not.
In Python 3.5.8 I can't use StringIO.StringIO
, but in io.BytesIO
the behavior is the same (noting I explicitly write b'a'
).
What causes this null byte to be prepended when I try to continually overwrite an io.BytesIO
instance, but not when I use StringIO.StringIO
?