StringIO в Python3

Я использую Python 3.2.1 и не могу импортировать модуль StringIO. Я использую io.StringIO и он работает, но я не могу использовать его с numpy genfromtxt например:

x="1 3\n 4.5 8"        
numpy.genfromtxt(io.StringIO(x))

Я получаю следующую ошибку:

TypeError: Can't convert 'bytes' object to str implicitly  

и когда я пишу import StringIO он говорит

ImportError: No module named 'StringIO'

Ответ 1

  когда я пишу import StringIO, он говорит, что такого модуля нет.

Из Что нового в Python 3.0:

Модули StringIO и cStringIO исчезли. Вместо этого импортируйте io модуль и использовать io.StringIO или io.BytesIO для текста и данных соответственно.

.


Возможно, полезный метод исправления кода Python 2 для работы в Python 3 (caveat emptor):

try:
    from StringIO import StringIO ## for Python 2
except ImportError:
    from io import StringIO ## for Python 3

Примечание. Этот пример может быть касательным к основной проблеме вопроса и включен только в качестве того, что следует учитывать при общем рассмотрении отсутствующего модуля StringIO. Для более прямого решения сообщения TypeError: Can't convert 'bytes' object to str implicitly см. этот ответ.

Ответ 2

В моем случае я использовал:

from io import StringIO

Ответ 3

В Python 3 numpy.genfromtxt ожидает поток байтов. Используйте следующее:

numpy.genfromtxt(io.BytesIO(x.encode()))

Ответ 4

Спасибо ОП за ваш вопрос, а Роман за ваш ответ. Мне пришлось немного поискать, чтобы найти это; Я надеюсь, что следующее поможет другим.

Python 2.7

Смотрите: 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.]]
"""

Python 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.]]
"""

Помимо:

dtype = "| Sx", где x = любой из {1, 2, 3,...}:

dtypes. Разница между S1 и S2 в Python

"Строки | S1 и | S2 являются дескрипторами типа данных; первая означает, что массив содержит строки длины 1, вторая - длины 2...."

Ответ 5

С помощью six:

import six
import numpy

x = "1 3\n 4.5 8"
numpy.genfromtxt(six.StringIO(x))

Ответ 6

Код Романа Шаповалова должен работать как в Python 3.x, так и в Python 2.6/2.7. Вот снова с полным примером:

import io
import numpy
x = "1 3\n 4.5 8"
numpy.genfromtxt(io.BytesIO(x.encode()))

Выход:

array([[ 1. ,  3. ],
       [ 4.5,  8. ]])

Объяснение для Python 3.x:

  • numpy.genfromtxt принимает поток байтов (подобный файлу объект, интерпретируемый как байты вместо Unicode).
  • io.BytesIO принимает строку байтов и возвращает поток байтов. io.StringIO, с другой стороны, будет принимать строку Unicode и возвращать поток Unicode.
  • x получает строковый литерал, который в Python 3.x является строкой Юникода.
  • encode() берет строку Unicode x и делает из нее строку байтов, тем самым давая io.BytesIO действительный аргумент.

Единственное отличие для Python 2.6/2.7 состоит в том, что x является байтовой строкой (при условии, что from __future__ import unicode_literals не используется), а затем encode() извлекает байтовую строку x и по-прежнему создает из нее ту же байтовую строку. Так что результат тот же.


Поскольку это один из самых популярных вопросов, касающихся StringIO, здесь приведено еще несколько пояснений по операторам импорта и различным версиям Python.

Вот классы, которые принимают строку и возвращают поток:

  • io.BytesIO (Python 2.6, 2.7 и 3.x) - принимает строку байта. Возвращает поток байтов.
  • io.StringIO (Python 2.6, 2.7 и 3.x) - принимает строку Unicode. Возвращает поток Unicode.
  • StringIO.StringIO (Python 2.x) - принимает строку байта или строку Юникода. Если строка байтов, возвращает поток байтов. Если строка Unicode, возвращает поток Unicode.
  • cStringIO.StringIO (Python 2.x) - более быстрая версия StringIO.StringIO, но не может принимать строки Unicode, содержащие символы не ASCII.

Обратите внимание, что StringIO.StringIO импортируется как from StringIO import StringIO, а затем используется как StringIO(...). Либо так, либо вы делаете import StringIO, а затем используете StringIO.StringIO(...). Имя модуля и имя класса просто совпадают. Это похоже на datetime таким образом.

Что использовать, в зависимости от поддерживаемых версий Python:

  • Если вы поддерживаете только Python 3.x: просто используйте io.BytesIO или io.StringIO в зависимости от того, с какими данными вы работаете.

  • Если вы поддерживаете Python 2.6/2.7 и 3.x или пытаетесь перевести ваш код с 2.6/2.7 на 3.x: самый простой вариант - использовать io.BytesIO или io.StringIO. Хотя StringIO.StringIO является гибким и поэтому кажется предпочтительным для 2.6/2.7, эта гибкость может маскировать ошибки, которые будут проявляться в 3.x. Например, у меня был некоторый код, который использовал StringIO.StringIO или io.StringIO в зависимости от версии Python, но на самом деле я передавал байтовую строку, поэтому, когда я приступил к тестированию в Python 3.x, он потерпел неудачу и должен был быть исправлен.

    Еще одним преимуществом использования io.StringIO является поддержка универсальных переносов строк. Если вы передадите аргумент ключевого слова newline='' в io.StringIO, он сможет разбить строки на любой из \n, \r\n или \r. Я обнаружил, что StringIO.StringIO, в частности, сработает на \r.

    Обратите внимание, что если вы импортируете BytesIO или StringIO из six, вы получаете StringIO.StringIO в Python 2.x и соответствующий класс из io в Python 3.x. Если вы согласны с оценкой моих предыдущих абзацев, то на самом деле это один из случаев, когда вам следует избегать six и просто импортировать из io.

  • Если вы поддерживаете Python 2.5 или ниже и 3.x: вам понадобится StringIO.StringIO для 2.5 или ниже, поэтому вы также можете использовать six. Но имейте в виду, что в целом очень трудно поддерживать как 2.5, так и 3.x, поэтому вам следует рассмотреть возможность увеличения вашей самой низкой поддерживаемой версии до 2.6, если это вообще возможно.

Ответ 7

Чтобы приведенные здесь примеры работали с Python 3.5.2, вы можете переписать следующее:

import io
data =io.BytesIO(b"1, 2, 3\n4, 5, 6") 
import numpy
numpy.genfromtxt(data, delimiter=",")

Причиной изменения может быть то, что содержимое файла находится в данных (байтах), которые не создают текст, пока не будут каким-либо образом декодированы. genfrombytes может быть лучшим именем, чем genfromtxt.

Ответ 8

попробуйте это

из StringIO import StringIO

x = "1 3\n 4,5 8"

numpy.genfromtxt(StringIO (х))