我需要在一个二进制文件中处理数十GB的数据。数据文件中的每条记录都是可变长度。
所以文件就像:
<len1><data1><len2><data2>..........<lenN><dataN>
数据包含整数,指针,双精度值等。
我发现python甚至无法处理这种情况。如果我在内存中读取整个文件没有问题。它很快。但似乎struct
包不擅长性能。它几乎坚持解压缩字节。
感谢任何帮助。
感谢。
答案 0 :(得分:5)
struct
和array
对于实现的细节很好,如果您的需求总是按顺序读取所有文件或前缀,则可能只需要它们它的。其他选项包括buffer,mmap,甚至ctypes,具体取决于您未提及的有关您的确切需求的许多详细信息。如果没有合适且可访问的库(在C,C ++,Fortran等中)已经存在,可以为了处理这个庞大的文件而进行接口,那么也许一个专门的Cython编码助手可以提供您所需的所有额外性能。你需要。
但显然这里存在一些特殊问题 - 例如,数据文件如何包含指针,这本质上是一个与寻址内存相关的概念?它们可能是“抵消”,如果是这样,它们究竟是如何基于和编码的?您的需求是否比简单的顺序读取(例如,随机访问)更先进,如果是这样,您是否可以进行第一次“索引”传递以将所有从文件开始到记录开始的偏移变为更可用,更紧凑的,手工格式化的辅助文件? ( 偏移量的二进制文件对于array
来说是很自然的 - 除非偏移量需要比机器上的array
支持更长!)。记录长度和组成的分布以及构成“数十千兆字节”的记录数量是多少?等等。
你有一个非常大规模的问题(毫无疑问是非常大规模的硬件支持它,因为你提到你可以轻松地将所有文件读入内存,这意味着一个64位的盒子有几十GB的RAM - 哇!),所以非常值得细致处理以优化其处理 - 但除非我们知道足够的细节,否则我们对这种详细的护理无能为力! - 。)。
答案 1 :(得分:2)
答案 2 :(得分:2)
对于类似的任务,我定义了一个这样的类:
class foo(Structure):
_fields_ = [("myint", c_uint32)]
创建了一个实例
bar = foo()
并且做了,
block = file.read(sizeof(bar))
memmove(addressof(bar), block, sizeof(bar))
如果是可变大小的记录,您可以使用类似的方法来检索 lenN ,然后读取相应的数据条目。实现起来似乎微不足道。但是,我不知道这个方法与使用 pack()和 unpack()相比有多快,也许其他人已经描述了这两种方法。
答案 3 :(得分:2)
有关解析文件而不将其读入内存的帮助,您可以使用bitstring模块。
在内部,这是使用struct模块和bytearray,但是不可变的Bits对象可以用文件名初始化,因此它不会将它全部读入内存。
例如:
from bitstring import Bits
s = Bits(filename='your_file')
while s.bytepos != s.length:
# Read a byte and interpret as an unsigned integer
length = s.read('uint:8')
# Read 'length' bytes and convert to a Python string
data = s.read(length*8).bytes
# Now do whatever you want with the data
当然,您可以根据需要解析数据。
您也可以使用切片表示法来读取文件内容,但请注意索引将以位而不是字节为例,因此例如s[-800:]
将是最后的100个字节。
答案 4 :(得分:1)
如果您将数据文件转储到内存中的sqlite3,该怎么办?
import sqlite3
sqlite3.Connection(":memory:")
然后,您可以使用sql处理数据。
此外,您可能希望查看generators(或here)和iterators(或here和here)。
答案 5 :(得分:1)