在附加模式下使用numpy.save加载保存的数组

Eya*_*tan 4 python load numpy append save

我在追加模式下使用numpy.save()保存数组:

f = open("try.npy", 'ab')
sp.save(f,[1, 2, 3, 4, 5])
sp.save(f,[6, 7, 8, 9, 10])
f.close()
Run Code Online (Sandbox Code Playgroud)

我可以在LIFO模式下加载数据吗?也就是说,如果我现在要加载6-10阵列,我是否需要加载两次(使用b):

f = open("try.npy", 'r')
a = sp.load(f)
b = sp.load(f)
f.close()
Run Code Online (Sandbox Code Playgroud)

或者我可以直接加载第二个附加保存?

hpa*_*ulj 5

我有点惊讶这个顺序保存和加载工作.我认为没有记录(请纠正我).但显然每个save都是一个自包含的单元,并且load读取到该单元的末尾,而不是文件的末尾.

把每个想象load成一个readline.你不能只读取文件的最后一行; 你必须阅读之前的所有内容.

好吧 - 有一种方法可以读取最后一个 - seek用于将文件读取移动到特定点.但要做到这一点,你必须确切知道所需的块开始的位置.

np.savez 是将多个数组保存到文件,或者更确切地说是zip存档的预期方法.


save保存两个部分,一个包含信息的标题dtype,shapestrides,以及数组缓冲区的副本.该nbytes属性给出了数据缓冲区的大小.至少这是数字和字符串dtypes的情况.

savedoc有一个使用打开文件的示例 - seek(0)用于回放文件以供使用load.

np.lib.npyio.format有关保存格式的更多信息.看起来可以通过读取前几个字节来确定标头的长度.您可以使用模块中的函数来执行所有这些读取和计算.


如果我从示例中读取整个文件,我得到:

In [696]: f.read()
Out[696]: 
b"\x93NUMPY\x01\x00F\x00
{'descr': '<i4', 'fortran_order': False, 'shape': (5,), }\n
 \x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00
\x93NUMPY\x01\x00F\x00
{'descr': '<i4', 'fortran_order': False, 'shape': (5,), }\n
 \x06\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\t\x00\x00\x00\n\x00\x00\x00"
Run Code Online (Sandbox Code Playgroud)

我添加了换行符以突出显示此文件的不同部分.请注意,每个都save\x93NUMPY.

使用打开的文件f,我可以读取标题(或第一个数组):

In [707]: np.lib.npyio.format.read_magic(f)
Out[707]: (1, 0)
In [708]: np.lib.npyio.format.read_array_header_1_0(f)
Out[708]: ((5,), False, dtype('int32'))
Run Code Online (Sandbox Code Playgroud)

我可以加载数据:

In [722]: np.fromfile(f, dtype=np.int32, count=5)
Out[722]: array([1, 2, 3, 4, 5])
Run Code Online (Sandbox Code Playgroud)

我从np.lib.npyio.format.read_array功能代码中推断出这一点.

现在该文件位于:

In [724]: f.tell()
Out[724]: 100
Run Code Online (Sandbox Code Playgroud)

这是下一个数组的头部:

In [725]: np.lib.npyio.format.read_magic(f)
Out[725]: (1, 0)
In [726]: np.lib.npyio.format.read_array_header_1_0(f)
Out[726]: ((5,), False, dtype('int32'))
In [727]: np.fromfile(f, dtype=np.int32, count=5)
Out[727]: array([ 6,  7,  8,  9, 10])
Run Code Online (Sandbox Code Playgroud)

我们在EOF.

并且知道int32有4个字节,我们可以计算出数据占用20个字节.因此,我们可以通过读取标题跳过数组,计算数据块的大小,然后seek通过它来到达下一个数组.对于工作不值得的小阵列; 但对于非常大的,它可能是有用的.