读取非常大的文件,其中格式是换行符独立的

时间:2010-11-11 19:09:04

标签: python file-io newline

我的Python代码支持以其他名为BLT format的人创建的文件格式读写数据。 BLT格式是空格和换行符独立,因为换行符就像其他空格一样。这种格式的主要条目是“选票”,以“0”结尾,例如,

1 2 3 0

由于格式与换行符无关,因此也可以写为

1 2
3 0

或者你可以在一条线上进行多次投票:

1 2 3 0 4 5 6 0

这些文件可能非常大,所以我不想将整个文件读入内存。基于行的读取很复杂,因为数据不是基于行的。以节省内存的方式处理这些文件的好方法是什么?

2 个答案:

答案 0 :(得分:3)

对我来说,解决这个问题最直接的方法是使用发电机。

def tokens(filename):
    with open(filename) as infile:
        for line in infile:
            for item in line.split():
                yield int(item)

def ballots(tokens):
    ballot = []
    for t in tokens:
        if t:
            ballot.append(t)
        else:
            yield ballot
            ballot = []

t = tokens("datafile.txt")

for b in ballots(t):
    print b

我看到@katrielalex发布了一个使用生成器的解决方案,而我发布了我的解决方案。我们之间的区别在于我使用了两个独立的生成器,一个用于文件中的单个标记,另一个用于您要解析的特定数据结构。前者作为参数传递给后者,基本思想是您可以为要解析的每个数据结构编写类似ballots()的函数。您可以迭代生成器生成的所有内容,或者在任一生成器上调用next()以获取下一个标记或选票(在用完时准备好StopIteration异常,或者将生成器写入在用完实际数据时生成None之类的标记值,并检查该值。

将整个事物包装在一个类中是非常简单的。事实上......

class Parser(object):

    def __init__(self, filename):

        def tokens(filename):
            with open(filename) as infile:
                for line in infile:
                    for item in line.split():
                        yield int(item)

        self.tokens = tokens(filename)

    def ballots(self):
        ballot = []
        for t in self.tokens:
            if t:
                ballot.append(t)
            else:
                yield ballot
                ballot = []

p = Parser("datafile.txt")

for b in p.ballots():
    print b

答案 1 :(得分:1)

使用generator

>>> def ballots(f):
...     ballots = []
...     for line in f:
...             for token in line.split():
...                     if token == '0':
...                             yield ballots
...                             ballots = []
...                     else:
...                             ballots.append(token)

这将逐行读取文件,在所有空格上拆分,然后将行中的标记逐个附加到列表中。每当达到零时,该选票为yield并且列表重置为空。