使用readline的python采样会产生内存错误



我尝试对一个超过2.6亿行的数据文件进行采样,创建了一个固定大小为1000个样本的均匀分布样本。

我所做的是:

import random
file = "input.txt"
output = open("output.txt", "w+", encoding = "utf-8")
samples = random.sample(range(1, 264000000), 1000)
samples.sort(reverse=False)
with open(file, encoding = "utf-8") as fp:
line = fp.readline()
count = 0
while line:
if count in samples:
output.write(line)
samples.remove(count)
count += 1
line = fp.readline()

此代码导致内存错误,没有进一步的描述。为什么这个代码会产生内存错误?

据我所知,它应该逐行读取我的文件。这个文件是28.4GB,所以不能作为一个整体读取,这就是我使用readline((方法的原因。如何修复此问题,以便可以处理整个文件,而不管其大小?\

编辑:最近的尝试抛出了这个错误,它实际上与我迄今为止收到的每个错误消息完全相同

MemoryError                               Traceback (most recent call last)
<ipython-input-1-a772dad1ea5a> in <module>()
12 with open(file, encoding = "utf-8") as fp:
13     count = 0
---> 14     for line in fp:
15         if count in samples:
16             output.write(line)
~Anaconda3libcodecs.py in decode(self, input, final)
320         # decode input (taking the buffer into account)
321         data = self.buffer + input
--> 322         (result, consumed) = self._buffer_decode(data, self.errors, final)
323         # keep undecoded input until the next call
324         self.buffer = data[consumed:]
MemoryError: 

因此,看起来这一行会导致巨大的内存峰值:

samples = random.sample(range(1, 264000000), 1000)

我的猜测是,这个调用迫使python在进行采样之前创建该范围内的所有264M int。尝试使用此代码在相同范围内采样而不进行替换:

from random import randint
file = "input.txt"
output = open("output.txt", "w+", encoding = "utf-8")
samples = set()
while len(samples) < 1000:
random_num = randint(0, 264000000)
if random_num not in samples:
samples.add(random_num)
with open(file, encoding = "utf-8") as fp:
count = 0
for line in fp:
if count in samples:
output.write(line)
samples.remove(count)
count += 1
if not samples: break

已解决

我终于解决了问题:这里的所有代码都能正常工作,范围问题实际上仅存在于3.0之前的版本中,其中它应该是xrange(126400000(。

输入文件被构造在不同的代码文件中,其内容如下:

with open(file, encoding = "utf-8", errors = 'ignore') as fp:  
line = fp.readline()
while line:
input_line = line.split(sep="t")
output.write(input_line[1] + "," + input_line[2])
line = fp.readline()

这里的问题是,这段代码没有用行构造文件,只是在第一行中添加信息。因此,整个文件被读取为一个大行,而不是一个有很多行要迭代的文件。

非常感谢您的帮助,并对问题出现在我项目的其他地方表示诚挚的歉意。

最新更新