我的需求是读取一个gain文件,由于这些文件会很大,我希望对其进行内存映射以获得I/O性能。
我尝试了以下代码:
import gzip
import mmap
with gzip.open("/home/test.json.gz", mode="r") as f:
with mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ) as f_mmap:
print(f_mmap.read())上面代码中的print语句输出一系列这样的十六进制作为输出:
b'\x1f\x8b当我尝试从上面的代码中删除mmap时,我看到了正确的预期结果。
你能帮助建议如何内存映射一个gzipped文件吗?
发布于 2021-11-02 12:40:29
mmap是原始文件访问;它从f (从gzip.open创建的对象)中唯一使用的是.fileno()方法,该方法获取原始文件描述符,它根本不知道文件是压缩的(gzip.open将原始文件描述符包装在按需执行解压缩的层中,但低级文件描述符对此一无所知)。
为了解决一些困惑:mmap并没有给你带来神奇的I/O性能提升。它在以下情况下最有用:
对于像JSON这样的东西,随机访问基本上是无用的;文件很可能是UTF-8文本,所以随机访问甚至不能保证在有效字符的开头,即使是这样,JSON中字符N的解释也取决于对字符0到N-1的解释(我们是在对象、数组、字符串等中吗?如果不知道其余部分,就不能知道)。所以#1不适用。
类似地,反复读取相同的JSON文件也没有什么好处;只需反序列化一次并使用它。
重点是,跳过mmap,直接做:
import json
import gzip
with gzip.open("/home/test.json.gz", mode="r") as f:
data = json.load(f)如果您的文件采用随机访问的格式,则仍然不能直接使用gzipped文件(压缩数据,如JSON,依赖于上下文;您需要先前字节的上下文来解释下一个字节)。如果出于某种原因必须使用mmap,则需要先将其解压,例如:
import gzip
import shutil
import tempfile
with tempfile.TemporaryFile() as f_temp: # Make an unnamed temporary file to use for mmap
with gzip.open("/home/test.data.gz") as f:
shutil.copyfileobj(f, f_temp) # Efficiently decompress from gzip to temp file
f_temp.flush() # Ensure no data stuck in user-mode buffers
# Memory map temporary file and use it
with mmap.mmap(f_temp.fileno(), length=0, access=mmap.ACCESS_READ) as f_mmap:
print(f_mmap.read())
# mapping closed and deleted outside its with
# temporary file closed and deleted outside its with在实践中,如果您经常重用这个文件,我建议您只将它以未压缩的形式存储,以避免每次使用前都进行解压缩,但我想我可以演示一下如何在您的实际用例需要的情况下使这样的东西工作。
https://stackoverflow.com/questions/69810349
复制相似问题