如何在 Python3 中使用 StringIO?

How do you use StringIO in Python3?

提问人:Babak Abdolahi 提问时间:8/11/2012 最后编辑:Josh CorreiaBabak Abdolahi 更新时间:10/12/2023 访问量:938620

问:

我正在使用 Python 3.2.1,但无法导入模块。我使用并且它有效,但我不能像这样使用它:StringIOio.StringIOnumpygenfromtxt()

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'
python-3.x io

评论


答:

79赞 Roman Shapovalov 8/15/2012 #1

在 Python 3 上,需要字节流。使用以下命令:numpy.genfromtxt

numpy.genfromtxt(io.BytesIO(x.encode()))
1065赞 Brent Bradburn 8/17/2013 #2

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

来自 Python 3.0 中的新增功能

和 模块不见了。相反,请导入模块并使用 或 用于文本和数据 分别。StringIOcStringIOioio.StringIOio.BytesIO

.


修复一些 Python 2 代码以使其在 Python 3 中也能工作的一种可能有用的方法(警告空头):

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

评论

14赞 Andy Hayden 4/22/2015
值得一提的是,这些是不一样的,所以如果你单独进行此更改,你最终会得到 s(字符串参数预期,得到“字节”)。您需要在 python 3 中仔细区分 btyes 和 str (unicode)。TypeError
8赞 Noumenon 7/8/2015
对于像我这样的新手:from io import StringIO 意味着您将其称为 StringIO(),而不是 io。StringIO() 中。
13赞 Oleh Prypin 8/12/2015
如何真正与 Python 2 和 3 兼容:只是from io import StringIO
9赞 Bill Huang 3/5/2016
这对于 python 3 中的 numpy.genfromtxt() 来说是完全错误的。请参考罗曼·沙波瓦洛夫(Roman Shapovalov)的回答。
3赞 Bill Huang 3/6/2016
@nobar:后者。原始问题使用 python 3.x,该模块已从中消失,应应用。在 python 3.5 @ eclipse pyDev + win7 x64 上测试了自己。如果我错了,请告诉我,谢谢。StringIOfrom io import BytesIO
172赞 Kamesh Jungi 3/17/2016 #3

就我而言,我使用了:

from io import StringIO
26赞 Victoria Stuart 5/23/2016 #4

感谢 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 的字符串。..."

24赞 Tiago Coutinho 6/1/2016 #5

您可以使用六个模块中的 StringIO

import six
import numpy

x = "1 3\n 4.5 8"
numpy.genfromtxt(six.StringIO(x))
7赞 Pierre ALBARÈDE 12/20/2016 #6

为了使这里的示例与 Python 3.5.2 一起使用,您可以按如下方式重写:

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

更改的原因可能是文件的内容以数据(字节)为单位,在以某种方式解码之前不会生成文本。 可能是一个比 更好的名称。genfrombytesgenfromtxt

27赞 S. Kirby 12/12/2018 #7

Roman Shapovalov 的代码应该可以在 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获取字节字符串并返回字节流。另一方面,将采用 Unicode 字符串并返回 Unicode 流。io.StringIO
  • x被分配一个字符串文字,在 Python 3.x 中是一个 Unicode 字符串。
  • encode()获取 Unicode 字符串并从中生成一个字节字符串,从而给出一个有效的参数。xio.BytesIO

Python 2.6/2.7 的唯一区别是,它是一个字节字符串(假设未使用),然后获取字节字符串并仍然从中制作相同的字节字符串。所以结果是一样的。xfrom __future__ import unicode_literalsencode()x


由于这是 SO 最受欢迎的问题之一,因此这里有一些关于 import 语句和不同 Python 版本的更多解释。StringIO

以下是接受字符串并返回流的类:

  • io。BytesIO (Python 2.6, 2.7, and 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) - 更快的版本,但不能接受包含非 ASCII 字符的 Unicode 字符串。StringIO.StringIO

请注意,它作为 导入,然后用作 。要么这样,要么你这样做,然后使用 .模块名和类名恰好相同。这与此类似。StringIO.StringIOfrom StringIO import StringIOStringIO(...)import StringIOStringIO.StringIO(...)datetime

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

  • 如果仅支持 Python 3.x:只需使用或取决于您正在处理的数据类型。io.BytesIOio.StringIO

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

    使用的另一个优点是支持通用换行符。如果将关键字参数传递到 ,它将能够拆分 、 或 中的任何一行。我发现这尤其会绊倒。io.StringIOnewline=''io.StringIO\n\r\n\rStringIO.StringIO\r

    请注意,如果从 6 导入 或,则在 Python 2.x 中获取相应的类,并在 Python 3.x 中获取相应的类。如果您同意我前面几段的评估,这实际上是您应该避免并改为导入的一种情况。BytesIOStringIOStringIO.StringIOiosixio

  • 如果您支持 Python 2.5 或更低版本以及 3.x:您需要 2.5 或更低的版本,因此您不妨使用 .但要意识到,通常很难同时支持 2.5 和 3.x,因此如果可能的话,您应该考虑将支持的最低版本提升到 2.6。StringIO.StringIOsix

-1赞 SM Mustafa 12/6/2020 #8

我希望这能满足你的要求

import PyPDF4
import io

pdfFile = open(r'test.pdf', 'rb')
pdfReader = PyPDF4.PdfFileReader(pdfFile)
pageObj = pdfReader.getPage(1)
pagetext = pageObj.extractText()

for line in io.StringIO(pagetext):
    print(line)
2赞 Trees 7/6/2021 #9

这是 Python 3 的另一个示例。它将使用两个函数添加两个数字,然后使用 CProfile 保存文件。然后它将使用 and '''StringIO'' 加载保存文件,将数据转换为字符串以供进一步使用。.profpstats.Stats

main.py

import cProfile
import time
import pstats
from io import StringIO

def add_slow(a, b):
    time.sleep(0.5)
    return a+b

def add_fast(a, b):
    return a+b

prof = cProfile.Profile()

def main_func():
    arr = []
    prof.enable()
    for i in range(10):
        if i%2==0:
            arr.append(add_slow(i,i))
        else:
            arr.append(add_fast(i,i))
    prof.disable()
    #prof.print_stats(sort='time')
    prof.dump_stats("main_funcs.prof")
    return arr

main_func()
stream = StringIO();
stats = pstats.Stats("main_funcs.prof", stream=stream); 
stats.print_stats()
stream.seek(0)
print(16*'=',"RESULTS",16*'=')
print (stream.read())

用法:

python3 main.py

输出:

================ RESULTS ================
Tue Jul  6 17:36:21 2021    main_funcs.prof

         26 function calls in 2.507 seconds

   Random listing order was used

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       10    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
        5    2.507    0.501    2.507    0.501 {built-in method time.sleep}
        5    0.000    0.000    2.507    0.501 profiler.py:39(add_slow)
        5    0.000    0.000    0.000    0.000 profiler.py:43(add_fast)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

点评:我们可以观察到,在上面的代码中,time.sleep 函数大约需要 2.507 秒。