如何在Python 3中使用StringIO?

ykejflvf  于 2023-10-21  发布在  Python
关注(0)|答案(9)|浏览(164)

我正在使用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'
1cosmwyk

1cosmwyk1#

当我写import StringIO时,它说没有这样的模块。
What’s New In 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
evrscar2

evrscar22#

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

from io import StringIO
2nbm6dog

2nbm6dog3#

在Python 3中,numpy.genfromtxt需要字节流。使用以下方法:

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

c3frrgcw4#

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

使用io.StringIO的另一个优点是支持通用换行符。如果将关键字参数newline=''传递给io.StringIO,它将能够拆分\n\r\n\r中的任何一个上的行。我发现StringIO.StringIO特别会在\r上出错。
请注意,如果从six导入BytesIOStringIO,则在Python 2.x中将获得StringIO.StringIO,而在Python 3.x中将获得来自io的相应类。如果你同意我前面的段落的评估,这实际上是一种情况,你应该避免six,而只是从io导入。

    • 如果你支持Python 2.5或更低版本和3.x:* 你需要StringIO.StringIO来支持2.5或更低版本,所以你也可以使用six。但是要意识到同时支持2.5和3.x通常是非常困难的,所以如果可能的话,你应该考虑将最低支持的版本提升到2.6。
1hdlvixo

1hdlvixo5#

谢谢你的问题,罗曼的回答。我找了半天才找到这个我希望以下内容能帮助到其他人。

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. Difference between S1 and S2 in Python
“那|S1和|S2字符串是数据类型描述符;第一个表示数组保存长度为1的字符串,第二个表示长度为2。...”

eulz3vhy

eulz3vhy6#

您可以使用six模块中的StringIO:

import six
import numpy

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

but5z9lq7#

为了让here的例子在Python 3.5.2中工作,你可以重写如下:

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

更改的原因可能是文件的内容是以数据(字节)形式存在的,这些数据在以某种方式解码之前不会生成文本。genfrombytes可能是一个比genfromtxt更好的名字。

qq24tv8q

qq24tv8q8#

下面是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}

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

mmvthczy

mmvthczy9#

希望能满足您的要求

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)

相关问题