读取大文件而不重新分配内存

问题描述 投票:0回答:2

当我想在 python 中读取内存中的二进制文件时,我只需这样做:

with open("file.bin","rb") as f:
    contents = f.read()

对于“合理”大小的文件,这是完美的,但是当文件很大时(例如,1Gb或更多),在监视进程时,我们注意到内存增加然后缩小,然后增加,...可能是

的影响realloc
在幕后,当原始内存块太小而无法容纳文件时。

做了好几次,这个

realloc
+
memmove
操作占用了大量的CPU时间。在 C 中,我不会遇到问题,因为我会将正确分配的缓冲区传递给
fread
(但在这里我不能,因为
bytes
对象是不可变的,所以我无法预分配)。

当然我可以像这样一块一块地读它:

with open("file.bin","rb") as f:
    while True:
        contents = f.read(CHUNK_SIZE)
        if contents:
            chunks.append(contents)
        else:
             break

但是我必须

join
字节块,但这在某些时候也会占用所需内存的两倍,而且我可能买不起。

是否有一种方法可以使用一个单独的大内存分配来读取缓冲区中的大二进制文件,并且在 CPU 方面高效?

python memory
2个回答
2
投票

您可以使用

os.open
方法,它基本上是 POSIX 系统调用
open
的包装器。

import os
fd = os.open("file.bin", os.O_RDONLY | os.O_BINARY)

这将以

rb
模式打开文件。

os.open
返回一个没有
read
方法的文件描述符。您必须一次读取
n
字节:

data = os.read(fd, 100)

完成后,使用

os.close
关闭文件:

os.close(fd)

您正在用 Python 读取文件,就像在 C 中一样!

这里有一些有用的参考:

  1. 官方文档
  2. 图书馆参考

免责声明:根据我对 C 的

open
函数如何工作的了解,我相信这 应该 可以解决问题。


2
投票
import mmap

def read_large_file(filename):
  with open(filename, "rb") as f:
      # Map the entire file into memory
    with mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ) as mm:
        # Access the file contents via the memory map
        file_contents = mm[:]
  return file_contents

# Usage
file_contents = read_large_file("file.bin")
  1. 我们以读取模式打开二进制文件。
  2. 我们使用 mmap.mmap() 创建一个内存映射对象,传递文件 描述符 (f.fileno())、长度(0 表示整个文件)和 访问模式(mmap.ACCESS_READ 表示只读访问)。
  3. 我们使用切片(mm[:])访问内存映射文件的内容 将整个文件读入字节对象。
© www.soinside.com 2019 - 2024. All rights reserved.