gpt4 book ai didi

python - 快速数据从文件移动到一些 StringIO

转载 作者:太空狗 更新时间:2023-10-29 21:21:23 28 4
gpt4 key购买 nike

在 Python 中,我有一个文件流,我想将它的一部分复制到 StringIO 中。我希望它尽可能快,副本最少。

但如果我这样做:

data = file.read(SIZE)
stream = StringIO(data)

我认为已经完成了 2 个副本,不是吗?一个从文件复制到数据,另一个在 StringIO 复制到内部缓冲区。我可以避免其中一份副本吗?我不需要临时数据,所以我认为一份就足够了

最佳答案

简而言之:使用 StringIO 无法避免 2 个副本。

一些假设:

  • 你正在使用 cStringIO,否则优化这么多就太傻了。
  • 您追求的是速度而不是内存效率。如果不是,请参阅 Jakob Bowyer 的解决方案,或者如果您的文件是二进制文件,则使用 file.read(SOME_BYTE_COUNT) 的变体。
  • 您已经在评论中说明了这一点,但为了完整起见:您想要实际编辑内容,而不仅仅是查看内容。

长答案:由于 python 字符串是不可变的,而 StringIO 缓冲区不是,迟早要复制一份;否则你会改变一个不可变的对象!对于您希望成为可能的情况,StringIO 对象需要有一个专用方法,该方法直接从作为参数给出的文件对象中读取。没有这样的方法。

在 StringIO 之外,有一些解决方案可以避免额外的复制。在我的脑海中,这将把一个文件直接读入一个可修改的字节数组,没有额外的副本:

import numpy as np
a = np.fromfile("filename.ext", dtype="uint8")

使用起来可能很麻烦,具体取决于您的用途,因为它是一个从 0 到 255 的值数组,而不是一个字符数组。但它在功能上等同于 StringIO 对象,并且使用 np.fromstringnp.tostringnp.tofile 和切片符号应该可以帮助您你要。您可能还需要 np.insertnp.deletenp.append

我确信还有其他模块可以做类似的事情。

时间:

这一切到底有多少重要?好吧,走着瞧。我制作了一个 100MB 的文件,largefile.bin。然后我使用这两种方法读入文件并更改第一个字节。

$ python -m timeit -s "import numpy as np" "a = np.fromfile('largefile.bin', 'uint8'); a[0] = 1"10 loops, best of 3: 132 msec per loop$ python -m timeit -s "from cStringIO import StringIO" "a = StringIO(); a.write(open('largefile.bin').read()); a.seek(0); a.write('1')"10 loops, best of 3: 203 msec per loop

所以在我的例子中,使用 StringIO 比使用 numpy 慢 50%。

最后,为了对比,直接编辑文件:

$ python -m timeit "a = open('largefile.bin', 'r+b'); a.seek(0); a.write('1')"10000 loops, best of 3: 29.5 usec per loop

所以,它快了将近 4500 倍。当然,这在很大程度上取决于您要对文件执行的操作。改变第一个字节几乎没有代表性。但是使用这种方法,您确实比其他两个方法先行一步,并且由于大多数操作系统都有良好的磁盘缓冲,因此速度也可能非常好。

(如果您不允许编辑文件,因此想避免制作工作副本的成本,有几种可能的方法可以提高速度。如果您可以选择文件系统,Btrfscopy-on-write 文件复制操作——使复制文件的行为几乎是即时的。使用任何文件系统的 LVM 快照可以实现相同的效果。)

关于python - 快速数据从文件移动到一些 StringIO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8240647/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com