是否有选项可以分块加载pickle文件?
我知道我们可以将数据保存在CSV中并分块加载它。 但除了CSV之外,是否有选项可以分块加载pickle文件或任何Python原生文件?
import pickle
filename = "myfile.pkl"
str_to_save = "myname"
with open(filename,'wb') as file_handle:
pickle.dump(str_to_save, file_handle)
with open(filename,'rb') as file_handle:
result = pickle.load(file_handle)
print(result)
这可以分成两个单独的pickle文件:
import pickle
filename_1 = "myfile_1.pkl"
filename_2 = "myfile_2.pkl"
str_to_save = "myname"
with open(filename_1,'wb') as file_handle:
pickle.dump(str_to_save[0:4], file_handle)
with open(filename_2,'wb') as file_handle:
pickle.dump(str_to_save[4:], file_handle)
with open(filename_1,'rb') as file_handle:
result = pickle.load(file_handle)
print(result)
import pickle
filename = "myfile.pkl"
str_to_save = "myname"
with open(filename,'wb') as file_handle:
pickle.dump(str_to_save[0:4], file_handle)
pickle.dump(str_to_save[4:], file_handle)
with open(filename,'rb') as file_handle:
result = pickle.load(file_handle)
print(result)
result = pickle.load(file_handle)
print(result)
pickle.dump()
一次性写入同一个文件中。 - AKX但是也许可以通过pickle“缓冲区”和“带外”功能实现非常大的数据的中间结果。
请注意,这并不完全是将单个pickle文件分段加载/保存。它仅适用于在序列化过程中遇到声明自己为“带外”(单独序列化)的对象。
如果buffer_callback不为None,则可以使用buffer view调用任意次数。如果回调返回false值(例如None),则给定的缓冲区为带外; 否则,缓冲区在带内序列化,即在pickle流中。(强调我的)
引用"Out of band" conceptdoc:
在某些情况下,pickle模块用于传输大量数据。因此,最小化内存复制的数量以保持性能和资源消耗可能非常重要。然而,pickle模块的正常操作将对象的图形结构转换为字节流的顺序流时,本质上涉及到从pickle流中复制数据。b = ZeroCopyByteArray(b"abc") # NB: class has a special __reduce_ex__ and _reconstruct method
buffers = []
data = pickle.dumps(b, protocol=5, buffer_callback=buffers.append)
# we could do things with these buffers like:
# - writing each to a single file,
# - sending them over network,
# ...
new_b = pickle.loads(data, buffers=buffers) # load in chunks
如果buffers不为None,则应该是可迭代的启用缓冲区的对象,每次pickle流引用带外缓冲区视图时都会消耗它们。这些缓冲区已按顺序提供给Pickler对象的buffer_callback。 自版本3.8起更改:添加了buffers参数。
我有一个类似的问题,在我编写一个文件描述符池时,注意到当我关闭文件描述符时,我的 pickle 文件会损坏。虽然您可以对打开的文件描述符执行多个 dump()
操作,但随后不可能执行 open('file', 'ab')
以开始保存新的对象集。
我通过在必须关闭文件描述符之前做一个pickler.dump(None)
作为会话终止器来解决这个问题,并重新打开时,我实例化了一个新的Pickler
实例来恢复向文件写入。
从此文件加载时,None
对象表示会话结束,在此时我使用文件描述符实例化一个新的Pickler
实例,以继续读取多会话 pickle 文件的其余部分。
但是,只有在某种原因下您必须关闭文件描述符时才适用于此。否则,任意数量的dump()
调用都可以执行后面的load()
。