如何在Python3中使用StringIO ?

我使用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'
870626 次浏览

在Python 3 numpy.genfromtxt上需要一个字节流。使用以下方法:

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

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

从# EYZ0:

StringIOcStringIO模块已经没有了。相反,导入io 模块和使用io.StringIOio.BytesIO的文本和数据 分别。< / p >


修复一些Python 2代码,使其在Python 3中也能正常工作的一个可能有用的方法(买者自负):

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

对于信息TypeError: Can't convert 'bytes' object to str implicitly的更直接的解决方案,请参阅这个答案

在我的例子中,我使用了:

from io import StringIO

谢谢OP的问题,谢谢Roman的回答。我费了好大劲才找到这个;我希望下面的内容能对其他人有所帮助。

Python 2.7

看到:# EYZ0

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,…}中的任意一个:

< a href = " https://stackoverflow.com/questions/14790130/dtypes-difference-between-s1-and-s2-in-python " > dtypes。Python中S1和S2的差异

“|S1和|S2字符串是数据类型描述符;第一个表示数组包含长度为1的字符串,第二个长度为2的字符串. ...”

你可以使用六个模块中的StringIO:

import six
import numpy


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

为了从这里做例子 在Python 3.5.2中,你可以重写如下

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

更改的原因可能是文件的内容是数据(字节),直到以某种方式解码才成为文本。genfrombytes可能比genfromtxt更好。

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接受一个字节字符串并返回一个字节流。另一方面,io.StringIO将接受一个Unicode字符串并返回一个Unicode流。
  • x被分配了一个字符串字面值,在Python 3中。x是一个Unicode字符串。
  • encode()接受Unicode字符串x并从中生成字节字符串,从而为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,这取决于您正在处理的数据类型。

  • 最简单的选择仍然是使用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上绊倒。

    注意,如果你从six导入BytesIOStringIO,你会在python2中得到StringIO.StringIO。Python 3.x中的io和相应的类。如果你同意我前面几段的评估,这实际上是一种你应该避免six而只是从io导入的情况

  • 如果您支持Python 2.5或更低版本和3。你将需要StringIO.StringIO为2.5或更低,所以你不妨使用six。但是要意识到同时支持2.5和3通常是非常困难的。因此,如果可能的话,您应该考虑将最低支持版本提高到2.6。

我希望这能满足你的要求

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)

下面是Python 3的另一个例子。它将使用两个函数来添加两个数字,然后使用CProfile保存.prof文件。然后它将使用pstats.Stats和' ' StringIO ' '加载保存文件,将数据转换为字符串以供进一步使用。

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}


注释:我们可以在上面的代码中观察到,时间。睡眠功能大约需要2.507秒。