随机化1.53亿行文件而不耗尽内存

2024-04-20 14:11:38 发布

您现在位置:Python中文网/ 问答频道 /正文

你好,我想随机化一个153mil行文本文件的行,但我使用的当前方式使我在执行时内存不足:

with open(inputfile,'r') as source:
    data = [ (random.random(), line) for line in source ]
    data.sort()
with open(outputfile,'w') as target:
    for _, line in data:
        target.write( line )

Tags: insourcetargetfordataaswith方式
3条回答

我将如何做到这一点,而不必读取全部内存中的数据,也不必太复杂:

首先计算文件中的最大行长(使用二进制模式)

with open(inputfile,'rb') as source:
    max_line_len = max(len(line) for line in source)

然后用正确的填充将另一个文件写入磁盘,使每一行的大小完全相同(您需要两倍以上的大小,但因为您没有内存…)。同时数一数线。你知道吗

with open(inputfile,'rb') as source, open(outputfile,'wb') as dest:
    for count,line in enumerate(source):
        dest.write(line + b"*"*(max_line_len-len(line))) # write padded

你刚刚创建了一个更大的文件,但现在行的长度完全相同。好吧,我们在linefeed后面加了,以后会有用的。示例输出为(例如,如果max len=20):

the first line
****the second line
***another line
******

(不确定添加的星星的确切数目,但您知道了,注意填充字符并不重要,只要它不是\n

这意味着您可以通过max_line_len(如记录文件或数据库)的简单乘法在任何行的开头进行查找

现在可以生成行索引列表:

indexes = list(range(count+1))
random.shuffle(indexes)

现在迭代这个索引列表,寻找合适的位置,读取一个块并使用在linefeed之后填充的事实进行拆分,这样现在我们可以拆分它以丢弃填充内容。你知道吗

with open(outputfile,'rb') as source:
   for idx in indexes:
       source.seek(idx * max_line_len)
       random_line = source.read(max_line_len).decode().split("\n")[0]
       print(random_line) # or store to another file

我还没有测试这个,但它应该工作,如果你有足够的磁盘。当然,这是非常浪费,如果你有一个很长的线,其余的都很短。你知道吗

使用h5py,可以将数据文件移植为HDF5格式,然后随机化:

https://stackoverflow.com/a/44866734/3841261

You can use random.shuffle(dataset). This takes a little more than 11 minutes for a 30 GB dataset on my laptop with a Core i5 processor, 8 GB of RAM, and a 256 GB SSD

做一些粗略的餐巾纸计算,估计每行120个字符乘以153m行。。。计算出来大约有18.5 GB的数据。(我假设每个字符有1个字节,但是由于使用Unicode,这会更复杂。。。不过,你明白了)。因此,为了完全读入文本,您至少需要这个数量的RAM。这就是为什么在read-in上出现内存不足异常。你知道吗

你可以采取的一种方法是把工作分成几部分。读入文件的某些部分,将它们随机排列,然后附加到新文件中,写入文件并在运行时清除内存。当然,问题是,你只能在特定的块内随机化。你知道吗

你可以采取很多方法,但是你不能回避这样一个事实:如果你没有记忆,你不能一次读完所有的课文。你知道吗

编辑

我真的很喜欢查德使用h5py和HDF5的想法。它基本上是在硬盘上的一个文件中进行所有的洗牌。。。有点像强制交换硬盘驱动器,但有更多的控制。我喜欢!不过,这确实需要有h5py。你知道吗

相关问题 更多 >