Python3中的StringIO


473

我正在使用Python 3.2.1,但无法导入StringIO模块。我使用 io.StringIO和它的作品,但我不能使用它numpygenfromtxt是这样的:

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'

Answers:


771

当我写导入StringIO时,它说没有这样的模块。

Python 3.0的新功能开始

StringIOcStringIO模块都没有了。而是导入io 模块,分别将io.StringIOio.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,请参阅此答案


13
值得一提的是它们并不相同,因此TypeError,如果您单独进行此更改,则可以以s(期望的字符串参数,得到“ bytes”)结尾。你需要在Python 3.仔细辨别btyes和STR(UNICODE)
安迪·海登

7
对于像我这样的新手:从io导入StringIO意味着您将其称为StringIO(),而不是io.StringIO()。
Noumenon 2015年

11
如何实际与Python 2和3兼容:刚刚from io import StringIO
Oleh Prypin 2015年

8
对于python 3中的numpy.genfromtxt(),这很简单。请参阅Roman Shapovalov的回答。
Bill Huang

2
@nobar:后者。最初的问题使用的是python 3.x,不再使用该模块StringIOfrom io import BytesIO应改用python3.x。在python 3.5 @ eclipse pyDev + win7 x64上测试了自己。如果我错了,请告诉我。
Bill Huang



24

谢谢OP的问题,以及Roman的回答。我不得不花点时间找到它。希望以下内容对其他人有所帮助。

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。Python中S1和S2之间的区别

“ | S1和| S2字符串是数据类型描述符;第一个意味着数组保存长度为1的字符串,第二个长度为2。...”



17

Roman Shapovalov的代码应该在Python 3.x和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中是Unicode字符串。
  • encode()x提取Unicode字符串并从中取出一个字节字符串,从而提供io.BytesIO有效的参数。

Python 2.6 / 2.7的唯一区别是它x是一个字节字符串(假定from __future__ import unicode_literals未使用),然后encode()获取该字节字符串,x并仍然从中提取相同的字节字符串。因此结果是相同的。


由于这是SO最受欢迎的问题之一,因此StringIO,这里有一些有关import语句和不同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字符串,则返回Unicode流。
  • cStringIO.StringIO(Python 2.x)-的更快版本StringIO.StringIO,但不能采用包含非ASCII字符的Unicode字符串。

请注意,StringIO.StringIO导入为from StringIO import StringIO,然后用作StringIO(...)。要么这样做,要么您执行import StringIO然后使用StringIO.StringIO(...)。模块名称和类名称恰好是相同的。这类似于datetime这种方式。

使用什么,取决于您支持的Python版本:

  • 如果您仅支持Python 3.x:只需使用io.BytesIOio.StringIO取决于您使用的是哪种数据。

  • 如果您同时支持Python 2.6 / 2.7和3.x,或者正尝试将代码从2.6 / 2.7转换到3.x:最简单的选择仍然是使用io.BytesIOio.StringIO。尽管它StringIO.StringIO很灵活,因此在2.6 / 2.7中似乎是首选,但这种灵活性可能会掩盖3.x版本中将出现的错误。例如,我有一些使用StringIO.StringIOio.StringIO取决于Python版本的代码,但实际上是传递一个字节字符串,因此当我在Python 3.x中进行测试时,它失败了,必须加以修复。

    使用的另一个优点io.StringIO是对通用换行符的支持。如果你传递关键字参数newline=''io.StringIO,这将是能够在任何的分割线\n\r\n\r。我发现那StringIO.StringIO会绊倒\r尤其严重。

    请注意,如果您导入BytesIOStringIOsix,你StringIO.StringIO在Python 2.x和相应的类从io在Python 3.x的 如果您同意我之前的评估,实际上这是应该避免的一种情况,而应该six从中io引入。

  • 如果您支持Python 2.5或更低版本和3.x:您将需要StringIO.StringIO2.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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.