numpy.memmap映射保存文件

5 投票
2 回答
3696 浏览
提问于 2025-04-18 02:41

我正在尝试创建一个随机矩阵,并使用numpy.save将它保存为二进制文件。

然后我想用numpy.memmap来映射这个文件,但似乎映射得不太对。

我该怎么解决这个问题呢?

看起来它读取了.npy文件的头部,我需要跳过开头的一些字节。

rows=6
cols=4

def create_matrix(rows,cols):
    data = (np.random.rand(rows,cols)*100).astype('uint8') #type for image [0 255] int8?
    return data

def save_matrix(filename, data):
    np.save(filename, data)

def load_matrix(filename):
    data= np.load(filename)
    return data

def test_mult_ram():
    A= create_matrix(rows,cols)
    A[1][2]= 42
    save_matrix("A.npy", A)
    A= load_matrix("A.npy")
    print A
    B= create_matrix(cols,rows)
    save_matrix("B.npy", B)
    B= load_matrix("B.npy")
    print B




fA = np.memmap('A.npy', dtype='uint8', mode='r', shape=(rows,cols))
fB = np.memmap('B.npy', dtype='uint8', mode='r', shape=(cols,rows))
print fA
print fB

更新:

我刚发现其实已经有一个np.lib.format.open_memmap的函数可以使用。

用法: a = np.lib.format.open_memmap('A.npy', dtype='uint8', mode='r+')

2 个回答

7

如果你的目标是打开用 np.save 保存的数组,并且想把它们当作内存映射文件来使用,那么你只需要用 np.load 并加上 mmap_mode 这个选项就可以了:

fA = np.load('A.npy', mmap_mode='r')
fB = np.load('B.npy', mmap_mode='r')

这样做的好处是,你可以利用存储在 .npy 文件里的头信息,这样它就能记录数组的形状和数据类型。

4

npy格式的文件开头有一个需要跳过的头部信息。这个头部由6个字节的魔法字符串 '\x93NUMPY' 开始,接着是2个字节的版本号,然后是2个字节的头部长度,最后是头部数据。

所以,如果你打开这个文件,找到头部的长度,就可以计算出要传给 np.memmap 的偏移量:

def load_npy_to_memmap(filename, dtype, shape):
    # npy format is documented here
    # https://github.com/numpy/numpy/blob/master/doc/neps/npy-format.txt
    with open(filename, 'r') as f:
        # skip magic string \x93NUMPY + 2 bytes major/minor version number
        # + 2 bytes little-endian unsigned short int
        junk, header_len = struct.unpack('<8sh', f.read(10))

    data= np.memmap(filename, dtype=dtype, shape=shape, offset=6+2+2+header_len)
    return data

import struct
import numpy as np
np.random.seed(1)
rows = 6
cols = 4

def create_matrix(rows, cols):
    data = (np.random.rand(
        rows, cols) * 100).astype('uint8')  # type for image [0 255] int8?
    return data

def save_matrix(filename, data):
    np.save(filename, data)

def load_matrix(filename):
    data= np.load(filename)
    return data

def load_npy_to_memmap(filename, dtype, shape):
    # npy format is documented here
    # https://github.com/numpy/numpy/blob/master/doc/neps/npy-format.txt
    with open(filename, 'r') as f:
        # skip magic string \x93NUMPY + 2 bytes major/minor version number
        # + 2 bytes little-endian unsigned short int
        junk, header_len = struct.unpack('<8sh', f.read(10))

    data= np.memmap(filename, dtype=dtype, shape=shape, offset=6+2+2+header_len)
    return data

def test_mult_ram():
    A = create_matrix(rows, cols)
    A[1][2] = 42
    save_matrix("A.npy", A)
    A = load_matrix("A.npy")
    print A
    B = create_matrix(cols, rows)
    save_matrix("B.npy", B)
    B = load_matrix("B.npy")
    print B

    fA = load_npy_to_memmap('A.npy', dtype='uint8', shape=(rows, cols))
    fB = load_npy_to_memmap('B.npy', dtype='uint8', shape=(cols, rows))
    print fA
    print fB
    np.testing.assert_equal(A, fA)
    np.testing.assert_equal(B, fB)

test_mult_ram()

撰写回答