提问人:trapdrap 提问时间:11/11/2023 最后编辑:trapdrap 更新时间:11/11/2023 访问量:54
在 Python 中将重复字节流附加到 IO
Appending a stream of repeated bytes to IO in Python
问:
我正在编写一个程序,该程序需要在 Python 中将大量重复字节写入文件。
为了简化问题,我将使用数据的表示形式。 始终是 的返回结果,并将是“重复数据”的任意表示buffer
open(file_name, "a+")
b"0"
假设我想将重复的数据写入 50,000 次,到目前为止,我已经想到了 3 种方法。
第一种方法是先在内存中生成数据,然后再写入(这会占用大量内存)
data = b"0" * 50_000
buffer.write(data)
第二种方法是将每次迭代都写在一个循环中(这非常慢)
for _ in range(50_000):
buffer.write(b"0")
最后,第三种方法是将两者结合起来,并编写更大的片段(这比第二种选择快得多,但比第一种慢,最重要的是,即使在使用时也会使用内存,而且总的来说,这种设计非常丑陋)
data_x1 = b"0"
data_x10 = b"0" * 10
data_x100 = b"0" * 100
data_x1000 = b"0" * 1000
# writing in a loop using bigger to smaller segments
# until there is no more to write
num_left = 50_000
while num_left > 0:
if num_left >= 1000:
buffer.write(data_x1000)
num_left -= 1000
elif num_left >= 100:
buffer.write(data_x100)
num_left -= 100
elif num_left >= 10:
buffer.write(data_x10)
num_left -= 10
else:
buffer.write(data_x1)
num_left -= 1
TLDR:目标是在不使用 Python 循环的情况下将一组指定的字节重复写入文件,也不首先在内存中生成整个序列。
我一直在研究 的 write 方法,并注意到它需要一个类似字节的对象。
如果可能的话,最佳方法是能够创建一个“类似字节”的对象来模拟重复数据流,缓冲区可以在不使用 Python 循环的情况下写入 x 次。BufferedWriter
答:
只需尽可能使最大的块,并将最后一个写入切成小块
# largest block you can put into memory
# replicate block until some limit
# must wrap at end if data isn't all the same
data = b"0" * 50_000
added_length = 120_000
with open(file_name, "ab+") as fh: # bytes mode makes math work
while fh.tell() < added_length:
fh.write(data[:added_length - fh.tell()]) # don't write too much
请注意,打开时,将从 开始,并且是初始文件结尾的偏移量。但是,如果您想同时阅读其他内容或获取总文件大小,您可能会发现打开和结束会更好"a"
.tell()
0
"r+"
.seek()
评论
fh.tell()
q, r = divmod(added_length, len(data))
data
q
r
IOError
如果您打算尝试使用大型缓冲区进行写入,则最好使用系统默认缓冲区大小。
import io
data = b'0' * io.DEFAULT_BUFFER_SIZE
full, extra = divmod(total_bytes_to_write, io.DEFAULT_BUFFER_SIZE)
with open(file_name, "ab+") as fh:
for _ in range(full):
fh.write(data)
fh.write(data[:extra]
通过使用默认缓冲区大小的倍数,可能会获得一点收益,但请务必在命令中也使用此值。open
import io
buffer_size = 4 * io.DEFAULT_BUFFER_SIZE
data = b'0' * buffer_size
full, extra = divmod(total_bytes_to_write, buffer+size)
with open(file_name, "ab+", buffering=buffer_size) as fh:
.. same as above ...
用户@trapdrap(见注释)声称,在所有情况下,您都应该在所有情况下使用,因为您不希望或不需要缓冲。buffering = 0
评论
buffering
buffering = 0
评论