У меня много больших файлов .npy, и я хотел бы читать их заголовки, не загружая файл в память. Я спрашиваю об этом, потому что мне нужна только информация заголовка, но загрузка всего файла замедляет вычисления.

0
danissimo1 6 Окт 2020 в 16:00

2 ответа

Лучший ответ

Да, numpy.lib.format - это соответствующий модуль, но он не очень хорошо документирован, как его использовать, и IMO должна быть более простая в использовании встроенная функция для этого. но ты можешь сделать это.

Сначала вам нужно определить версию формата файла, а затем использовать либо read_array_header_1_0, либо read_array_header_2_0. Вы также можете использовать внутреннюю функцию _read_array_header, которая, несмотря на то, что она внутренняя, на самом деле проще в использовании. Здесь я реализовал независимый от версии read_array_header:

import numpy.lib.format

def read_array_header(fobj):
    version = numpy.lib.format.read_magic(fobj)
    func_name = 'read_array_header_' + '_'.join(str(v) for v in version)
    func = getattr(numpy.lib.format, func_name)
    return func(fobj)

Применение:

>>> with open('test.npy', 'rb') as fobj:
...     print(read_array_header(fobj))
...
((10,), False, dtype('int64'))

Возвращает форму массива, независимо от того, является ли он F-смежным, и dtype.

3
Iguananaut 6 Окт 2020 в 13:19

Как правильно отметил user8408080 формат хорошо документирован.

Простая функция просмотра может быть:

import ast
import struct

def read_npy_meta(fh):
    magic = fh.read(6)
    assert magic == b"\x93NUMPY"
    version = fh.read(2)
    header_size, = struct.unpack("<h", fh.read(2))
    header = fh.read(header_size)
    return ast.literal_eval(header.decode("utf-8"))

Применение:

>>> with open("my_npy_file.npy", "rb") as f:
...     meta = read_npy_meta(f)
>>> meta
{'descr': '<i2', 'fortran_order': False, 'shape': (100, 100, 100)}
0
L3viathan 6 Окт 2020 в 13:18