Ошибка в модуле StringIO Python с использованием NumPy
Очень простой код:
import StringIO
import numpy as np
c = StringIO.StringIO()
c.write("1 0")
a = np.loadtxt(c)
print a
Я получаю пустой массив + предупреждение о том, что с является пустым файлом.
Я исправил это, добавив:
d=StringIO.StringIO(c.getvalue())
a = np.loadtxt(d)
Я думаю, что такого не должно происходить, что здесь происходит?
2 ответа
StringIO
это файл-подобный объект. Как таковой он имеет поведение, совместимое с файлом. Существует понятие указателя файла - текущей позиции в файле. Когда вы пишете данные в StringIO
Объект указатель файла корректируется до конца данных. Когда вы пытаетесь прочитать его, указатель файла уже находится в конце буфера, поэтому данные не возвращаются.
Чтобы прочитать его обратно, вы можете сделать одну из двух вещей:
- использование
StringIO.getvalue()
как вы уже обнаружили. Это возвращает данные от начала буфера, оставляя указатель файла без изменений. - использование
StringIO.seek(0)
переместить указатель файла в начало буфера и затем вызватьStringIO.read()
читать данные.
демонстрация
>>> from StringIO import StringIO
>>> s = StringIO()
>>> s.write('hi there')
>>> s.read()
''
>>> s.tell() # shows the current position of the file pointer
8
>>> s.getvalue()
'hi there'
>>> s.tell()
8
>>> s.read()
''
>>> s.seek(0)
>>> s.tell()
0
>>> s.read()
'hi there'
>>> s.tell()
8
>>> s.read()
''
Есть одно исключение из этого. Если вы предоставляете значение во время создания StringIO
буфер будет инициализирован значением, но указатель файла будет расположен в начале буфера:
>>> s = StringIO('hi there')
>>> s.tell()
0
>>> s.read()
'hi there'
>>> s.read()
''
>>> s.tell()
8
И именно поэтому он работает, когда вы используете
d=StringIO.StringIO(c.getvalue())
потому что вы инициализируете StringIO
объект во время создания, а указатель файла располагается в начале буфера.
Это потому, что "позиция" объекта файла находится в конце файла после записи. Поэтому, когда numpy читает его, он читает от конца файла до конца, что является ничем.
Найдите в начале файла, и тогда он работает:
>>> from StringIO import StringIO
>>> s = StringIO()
>>> s.write("1 2")
>>> s.read()
''
>>> s.seek(0)
>>> s.read()
'1 2'