При работе с библиотекой gzip
в Python очень часто я сталкивался с кодом, который использует функцию .read()
в шаблоне, который выглядит следующим образом:
with gzip.open(filename) as bytestream:
bytestream.read(16)
buf = bytestream.read(
IMAGE_SIZE * IMAGE_SIZE * num_images * NUM_CHANNELS
)
data = np.frombuffer(buf, dtype=np.uint8).astype(np.float32)
Пока язнакомый с шаблоном диспетчера контекста, я изо всех сил пытаюсь понять, что вообще делает первая строка кода в диспетчере контекста with
.
Это документация для функции read()
:
Чтение не более n символов из потока.
Чтение из нижележащего буфера, пока у нас не будет n символов или мы не нажмем EOF.Если n отрицательно или опущено, читайте до EOF.
Если это так, функциональная роль первой строки bytestream.read(16)
должна заключаться в чтении и, таким образом, пропуске первых 16 символов, предположительнопотому что они действуют как метаданные или заголовок.Однако, когда у меня есть несколько изображений, как я узнаю, как использовать 16
в качестве аргумента для вызова read
вместо, скажем, 32 или, 8 или 64?
Я вспомнил много раз, когда сталкивался с полностью идентичным кодом, описанным выше, за исключением того, что автор использовал bytestream.read(8)
вместо bytestream.read(16)
или, что вполне вероятно, любое другое значение.Копание в файл посимвольно не показывает видимого шаблона для определения длины символа заголовка.
Другими словами, как один определяет параметр, который будет использоваться при вызове функции read
? или как узнать длину символов заголовка в сжатом gzip-файле?
Я предположил, что это как-то связано с байтами, но после поиска в документации и онлайн-ссылках я не могу это подтвердить.
Воспроизводимые детали
Моя гипотеза, после бесчисленных часов устранения неполадок, состоит в том, что первые 16 символов представляют собой своего рода заголовок или метаданные.Итак, первая строка в этом коде - пропустить 16 символов и сохранить оставшиеся в переменной с именем buf
.Однако, копаясь в данных, я не нашел способа определить, почему или как было выбрано значение 16.Я прочитал байты символ за символом, а также попытался прочитать + и привести их к типу np.float
, но нет никаких заметных шаблонов, которые предполагают, что метаданные заканчиваются 16-м символом, а фактические данные начинаются 17-го.
Следующий код читает данные с этого сайта и извлекает первые 30 символов.Обратите внимание, что неразличимо, где строка заголовка «заканчивается» (шестнадцатая, очевидно, после второго появления \ x1c`), и данные начинаются:
import gzip
import numpy as np
train_data_filename = 'data_input/train-images-idx3-ubyte.gz'
IMAGE_SIZE = 28
NUM_CHANNELS = 1
def extract_data(filename, num_images):
with gzip.open(filename) as bytestream:
first30 = bytestream.read(30)
return first30
first30= extract_data(train_data_filename, 10)
print(first30)
# returns: b'\x00\x00\x08\x03\x00\x00\xea`\x00\x00\x00\x1c\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Если мы изменим код, чтобы привести их к виду np.float32
, так что все символы теперь были в числовом формате (с плавающей запятой), опять же не было очевидного шаблона, чтобы различать, где заканчиваются заголовок / метаданные и где начинаются данные.
Любая ссылка или совет будут очень благодарны!