在 zipfile 中的文件上使用 numpy.load

Use numpy.load on file within zipfile

我有一个 zip 文件,其中包含许多 npy 文件(file1.npyfile2.npyfile3.npy、...)。我想单独加载它们而不在文件系统上提取 zipfile。我尝试了很多东西,但我无法弄清楚。

我的猜测是:

import zipfile
import numpy as np

a = {}

with zipfile.ZipFile('myfiles.zip') as zipper:
    for p in zipper.namelist():
        with zipper.read(p) as f:
            a[p] = np.load(f)

有什么想法吗?

numpy 函数是否需要一个文件对象,而不是结果文本。对于 zip 文件,我通常会这样做:

with ZipFile(path, mode='r') as archive:
    with io.BufferedReader(archive.open(filename, mode='r')) as file:

我猜你应该将 zipper.open(p, mode='r') 传递给 np.load(f)。此外,我强烈建议您不要执行 zipper.read(p),因为它会立即读取内存中的整个文件。因此,使用您的代码约定,尝试:

with zipfile.ZipFile('myfiles.zip') as zipper:
    for p in zipper.namelist():
        with io.BufferedReader(zipper.open(p, mode='r')) as f:
            a[p] = np.load(f)

将 2 个数组保存到各自的文件中:

In [452]: np.save('x.npy',x)
In [453]: np.save('y.npy',y)

使用文件浏览器工具,创建一个zip文件,并尝试加载它:

In [454]: np.load('xy.zip')
Out[454]: <numpy.lib.npyio.NpzFile at 0xb48968ec>

看起来 np.load 检测到 zip 性质(与名称无关),并返回一个 NpzFile 对象。让我们将它分配给一个变量,然后尝试正常的 .npz 提取:

In [455]: xy=np.load('xy.zip')

In [456]: xy['x']
Out[456]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

In [457]: xy['y']
Out[457]: 
array([[ 0,  4,  8],
       [ 1,  5,  9],
       [ 2,  6, 10],
       [ 3,  7, 11]])

因此 load 可以对 npy 个文件中的任何 zip 个文件执行 lazy 加载,无论它是如何创建的。

我用 BytesIO 替换了 load。我不知道它是否有效,但可以工作并且更具可读性:)

with ZipFile(fname) as z:
    for p in zipper.namelist():
        tmp =  np.load(io.BytesIO(z.read(p)))