Python如何读取巨大的二进制文件(> 25GB)?

Posted

技术标签:

【中文标题】Python如何读取巨大的二进制文件(> 25GB)?【英文标题】:Python how can I read huge binary file(>25GB)? 【发布时间】:2017-05-27 17:48:24 【问题描述】:

我有 N 体模拟数据,必须在 python 中读取该文件。

它的大小超过 25GB,因此 file.read() 因内存不足而无法工作。

所以我写了这样的代码

with open("fullFoF_merger.cbin.z0.Run1", "rb") as mergertree:
    def param(data):
        result = "nowhid":data[0], "nexthid":data[2],"zi":data[10], 
                  "zip1":data[11], "F":data[4], "mass":data[9], 
                  "dlnM":data[5],"dM":data[12], "dlnJ":data[6],"dJ":data[13],
                  "dlnspin": data[7], "spin":data[8],
                  "G":data[14], "overden":data[15]
        return result

    num = 0

    while 1:
        num +=1

        binary_data = mergertree.read(4)

        if not binary_data : break

        n_max = struct.unpack('I', binary_data)


        binary_data = mergertree.read(64*n_max[0])

        Halo = [None]*n_max[0]


        for i in range(1,n_max[0]+1):
            data = struct.unpack("4i12f", binary_data[64*(i-1):64*(i)])
            Halo[i-1] = param(data)

        MergerQ = []+Halo


print(MergerQ)

print(num)

print("\n Run time \n --- %d seconds ---" %(time.time()-start_time))

在这个过程中,while循环在这段代码中计算了45470522次。但是当我在 python 中打印 MergerQ 时,它只显示一个像这样的字典数据

['nowhid': 53724, 'nexthid': 21912952, 'zi': 0.019874930381774902, 'zip1': -1.6510486602783203e-05, 'F': inf, 'mass': 67336740864.0, 'dlnM': 0.0, 'dM': 0.0, 'dlnJ': 0.1983184665441513, 'dJ': 8463334768640.0, 'dlnspin': 0.19668935239315033, 'spin': 0.012752866372466087, 'G': inf, 'overden': 1.0068886280059814]

我认为这是由于python变量的内存不足或内存限制造成的。

我该如何解决这个问题?

有没有办法读取整个数据并保存在 python 变量中?

并行计算可以是这段代码的解决方案吗?

我将等待您的评论。谢谢。

【问题讨论】:

我希望将所有内容加载到字典中,如果不购买更多 RAM,您将永远无法实现。然后你用这些数据做什么? 在每次循环迭代中重置 MergerQ。但看起来您的代码并没有真正的帮助,因为您似乎仍在加载所有数据,您只是一次做一点。除非您实际上可以增量地进行处理,否则您将无法使用这些数据。例如,如果您必须对每条记录的值求和,则可以一次读取一条记录,更新总和,然后丢弃实际记录。但是您不能保留所有记录中的所有数据;这会占用太多内存。 我将读取所有数据,然后按zi、mass和overden对数据进行排序。 【参考方案1】:

这一行是你的问题:

MergerQ = []+Halo

你清除MergerQ,把它放在你的循环之外:

num = 0
MergerQ = []

while 1:
    ...
    MergerQ += Halo

但不要指望拥有存储整个文件所需的内存量,如果您的文件那么大,您将需要大量内存和大量时间。

编辑

您很有可能能够成功运行您的代码,而无需太多的物理 RAM,因为您的操作系统可能会将其存储在您的硬盘中并在需要时获取它,但这将大量 strong> 增加运行时间。

尝试运行这段代码 sn-p 看看会发生什么(警告:如果你让这个运行时间过长,你的机器将变得无响应,很可能需要物理重置

a = []
while 1:
    a = [a, a]

希望您的脚本做出类似反应。

【讨论】:

感谢您的帮助!我考虑并行处理以减少运行时间。如果我使用自己的笔记本电脑并行处理会减少很多时间吗? 老实说,我没有做过很多 PP,但据我所知,它会减少运行时间但会增加内存使用率

以上是关于Python如何读取巨大的二进制文件(> 25GB)?的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中拆分一个巨大的文本文件

如何知道python中一行CSV文件的字节位置?

C++怎么把文件读取成16进制的,显示出来,或者16进制的写入文件.

在python中如何从二进制文件中读取信息

PHP如何将从二进制文件中读取的字节转换为数字

Python 3.5 与 2.7 之间字​​符串连接的巨大时间差异