Ошибка в модуле 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'
Другие вопросы по тегам