我应该使用python处理庞大的bz2-文件(5+ GB)。使用我的实际代码,我总是会遇到内存错误。我读到某个地方可以使用sqlite3处理该问题。这是正确的吗?如果是,我应该如何修改我的代码?
(我对使用sqlite3不太有经验...)

这是我的代码的实际开头:

import csv, bz2

names = ('ID', 'FORM')

filename = "huge-file.bz2"

with open(filename) as f:
    f = bz2.BZ2File(f, 'rb')
    reader = csv.DictReader(f, fieldnames=names, delimiter='\t')
    tokens = [sentence for sentence in reader]


在此之后,我需要经历“标记”。如果我能处理这个庞大的bz2-文件,那就太好了-因此,非常感谢您的帮助!非常感谢您的协助!

最佳答案

该文件很大,读取所有文件将不起作用,因为您的进程将耗尽内存。

解决方案是读取文件中的块/行,并在读取下一个块之前对其进行处理。

清单理解线

tokens = [sentence for sentence in reader]


正在将整个文件读取到tokens,这可能导致进程内存不足。

csv.DictReader可以逐行读取CSV记录,这意味着在每次迭代中,会将1行数据加载到内存中。

像这样:

with open(filename) as f:
    f = bz2.BZ2File(f, 'rb')
    reader = csv.DictReader(f, fieldnames=names, delimiter='\t')
    for sentence in reader:
       # do something with sentence (process/aggregate/store/etc.)
       pass


请注意,如果在添加的循环中,将sentence中的数据存储在另一个变量(例如tokens)中,则根据数据量的多少,可能仍会消耗大量内存。因此,最好将它们聚合,或为该数据使用其他类型的存储。

更新资料

关于在流程中使用某些先前的行(如注释中所述),您可以执行以下操作:

然后,您可以将前一行存储在另一个变量中,该变量在每次迭代时都会被替换。

或者,如果您需要多行(后退),则可以得到最后一个n行的列表。

怎么样

collections.dequemaxlen一起使用以跟踪最后的n行。从文件顶部的deque标准模块导入collections

from collections import deque

# rest of the code ...

last_sentences = deque(maxlen=5) # keep the previous lines as we need for processing new lines
for sentence in reader:
    # process the sentence
    last_sentences.append(sentence)


我建议使用上述解决方案,但您也可以使用列表自己实施,并手动跟踪其大小。

在循环之前定义一个空列表,在循环结束时检查列表的长度是否大于所需长度,从列表中删除较旧的项目,然后追加当前行。

last_sentences = [] # keep the previous lines as we need for processing new lines
for sentence in reader:
    # process the sentence
    if len(last_sentences) > 5: # make sure we won't keep all the previous sentences
        last_sentences = last_sentences[-5:]
    last_sentences.append(sentence)

10-05 20:24
查看更多