我不是专业人士,我一直在努力了解StringIO的确切用途。我一直在互联网上找一些例子。但是,几乎所有示例都是非常抽象的。他们只是展示“如何”使用它。但是它们都没有显示“为什么”和“在什么情况下”应该/将要使用它?提前致谢
ps不要与stackoverflow上的这个问题混淆:StringIO用法,用于比较string和StringIo。
我不是专业人士,我一直在努力了解StringIO的确切用途。我一直在互联网上找一些例子。但是,几乎所有示例都是非常抽象的。他们只是展示“如何”使用它。但是它们都没有显示“为什么”和“在什么情况下”应该/将要使用它?提前致谢
ps不要与stackoverflow上的这个问题混淆:StringIO用法,用于比较string和StringIo。
Answers:
当您有一些仅接收文件的API,但需要使用字符串时,可以使用它。例如,要使用Python 2中的gzip模块压缩字符串:
import gzip
import StringIO
stringio = StringIO.StringIO()
gzip_file = gzip.GzipFile(fileobj=stringio, mode='w')
gzip_file.write('Hello World')
gzip_file.close()
stringio.getvalue()
如果您想要一个像文件一样的文件对象,但又要写入内存中的字符串缓冲区:StringIO是工具。如果您要构建大型字符串(例如纯文本文档)并进行大量字符串连接,则可能会发现,仅使用StringIO而不是一堆mystr += 'more stuff\n'
类型的操作会更容易。
StringIO
是相当快,如果你正在处理的字符数据的多个兆字节相比,像表达式时,mystr += "more stuff\n"
在一个循环中,特别是如果你可以使用cStringIO.StringIO
,而不是只io.StringIO
。
$ python3 -m timeit -s "from io import StringIO; line = 'a'*80" $'s = StringIO()\nfor i in range(10000): s.write(line)\ns = s.getvalue()'
⇒ 500 loops, best of 5: 599 usec per loop
; python3 -m timeit -s "line = 'a'*80" $'s = ""\nfor i in range(10000): s += line'
⇒500 loops, best of 5: 588 usec per loop
cStringIO
甚至在Python 3中也不存在。很高兴看到天真的实现在3.x中得到了优化!
+=
在AFAICT 2和Python 2中也得到了很好的优化:+=
基准测试的版本是StringIO的十倍,是Python2中StringIO的三倍。(此外,您的帖子中提到了io.StringIO
;不是仅Python 3吗?)
我个人已将其用于以下几点:
整个文件缓存。我有一个脚本,可读取PDF并验证有关它们的各种信息。我正在使用的PDF库在其文档构造函数中使用一个打开的文件。我最初只是打开了我感兴趣阅读的PDF,但是当我更改它以立即将整个文件读取到内存中,然后将StringIO对象传递给PDF库时,脚本的运行时间减少了一半。
延迟打印。同一脚本在读取每个PDF之前都会打印一个标题。但是,我可以在命令行上指定是忽略其配置文件中的某些测试,还是仅包括某些测试。如果我忽略给定PDF的所有测试,则不希望打印标题,但在运行完测试之前,我不知道要运行多少测试(也可以动态定义测试)。因此,我通过更改标题将其捕获到StringIO对象中,sys.stdout
并指向它,每次运行测试时,我都会检查该对象中是否包含任何内容。如果是这样,我将其打印出来并将其重置为空。瞧,只有经过测试的PDF才会打印标题。
我已经用它代替了文本文件进行单元测试。
例如,要制作csv“文件”以进行熊猫测试(Python 3):
import io
f = io.StringIO("id,name\n1,brian\n2,amanda\n3,zoey\n")
df = pd.read_csv(f) # pandas takes a file path or a file-like object
从这里的文档:
文本I / O的内存流。调用close()方法时,将丢弃文本缓冲区。
可以通过提供initial_value来设置缓冲区的初始值。
方法getvalue():返回包含缓冲区全部内容的str。
这是StringIO用例的具体示例:直接将一些数据写入AWS s3,而无需在本地磁盘上创建文件:
import csv
import io
import boto3
data = [
["test", "data", "headers etc", "123","",],
["blah", "123", "35", "blah","",],
["abc", "def", "blah", "yep", "blah"]
]
bucket_name = 'bucket_name_here'
session = boto3.Session(
aws_access_key_id = "fake Access ID"),
aws_secret_access_key = "fake Secret key"),
region_name = "ap-southeast-2")
)
s3 = session.resource('s3')
with io.StringIO() as f:
writer = csv.writer(f, delimiter=",")
writer.writerows(data)
resp = s3.Object(bucket_name, "test.csv").put(Body=f.getvalue())
无需在本地磁盘上写入任何内容,即可享受S3上的新csv!
duck typing
D