当与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 个字符开始。
下面的代码读取数据这个网站 http://yann.lecun.com/exdb/mnist/并提取前 30 个字符。请注意,标题行“结束”的位置(显然是在第二次出现 \x1c` 之后的第 16 行)和数据开始的位置是难以辨别的:
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
,这样所有字符现在都是数字(浮点),同样没有明显的模式来区分标题/元数据结束的位置和数据开始的位置。
任何参考或建议将不胜感激!