Python 读取格式与换行无关的非常大的文件

Python 读取格式与换行无关的非常大的文件,python,file-io,newline,Python,File Io,Newline,我的Python代码支持以其他人创建的文件格式读取和写入数据,该文件名为。BLT格式是独立于空格和换行符的,因为换行符与其他空格一样处理。这种格式的主要条目是以“0”结尾的“选票”,例如: 由于格式与换行无关,因此也可以将其编写为 1 2 3 0 或者您可以在一行中有多张选票: 1 2 3 0 4 5 6 0 这些文件可能非常大,所以我不想将整个文件读入内存。基于行的读取非常复杂,因为数据不是基于行的。以节省内存的方式处理这些文件的好方法是什么?使用: 这将逐行读取文件,在所有空格上拆分,并

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

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

1 2
3 0
或者您可以在一行中有多张选票:

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

使用:

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

使用:


这将逐行读取文件,在所有空格上拆分,并将行中的标记逐个附加到列表中。无论何时达到零,该选票都将
yield
ed,列表将重置为空。

对我来说,最直接的解决方法是使用生成器

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
我看到@KatrieleAlex在我发布我的解决方案时发布了一个生成器。我们之间的区别在于,我使用两个独立的生成器,一个用于文件中的单个标记,另一个用于您希望解析的特定数据结构。前者作为参数传递给后者,其基本思想是,您可以为希望解析的每个数据结构编写一个函数,如
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

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

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
我看到@KatrieleAlex在我发布我的解决方案时发布了一个生成器。我们之间的区别是我使用了两个单独的生成器,一个用于文件中的单个标记,另一个用于您希望解析的特定数据结构。前者作为参数传递给后者,基本思想是您可以编写一个f函数类似于
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

我喜欢这个想法,但似乎对每个字符进行迭代会很慢……我想知道我是否可以获得内存效率和速度。在抱怨它有多慢之前,您可以尝试一下。:-)它一次只读取一行,所以它不像是对每个正在读取的项目都有I/O调用。它不会对每个字符进行迭代;
char
只是一个非常容易引起误解的名称,它可以包含
“-2”
“10”
(根据给定的链接)或(大概)
str(任何旧的整数)
@katriealex:你还需要编辑最后两句话:“逐个添加字符”和“列表重置为零”@John:我需要在写之前学会阅读……谢谢你指出=)我喜欢这个主意,但似乎迭代每个字符会很慢。。。我想知道我是否能提高内存效率和速度。在抱怨它有多慢之前,你可以试试看。:-)它一次只读取一行,所以它不像是对每个正在读取的项目都有I/O调用
char
对于可能包含
“-2”
“10”
(根据给定链接)或(大概)str(任意旧整数)@katriealex的数据来说是一个非常容易引起误解的名称:您还需要编辑最后两句话:“逐个追加字符”和“列表重置为零”@约翰:我需要在写作之前学会阅读。。。感谢您指出=)此解决方案(两个生成器)比一个生成器的答案更可取,但还不够。文件格式除“选票”结构外还有其他结构。因此,您需要一个生成器来将文件解析为标记(可以包含引号中的文本),并且每个不同的结构需要一个识别器(可能是生成器)。谢谢您的回答!与R的
扫描
或Fortran的
读取
相比,缺少一种现成的方法来获取文件中接下来的n项,这确实会损害Python中的数据搜索。这个实现非常聪明和高效,但对于语言新手来说并不明显。这个解决方案(两个生成器)比一个生成器的答案更可取,但还不够。文件格式除“选票”结构外还有其他结构。因此,您需要一个生成器来将文件解析为标记(可以包含引号中的文本),并且每个不同的结构需要一个识别器(可能是生成器)。谢谢您的回答!与R的
扫描
或Fortran的
读取
相比,缺少一种现成的方法来获取文件中接下来的n项,这确实会损害Python中的数据搜索。这个实现非常聪明和高效,但对于语言新手来说并不明显。您对普通BLT格式还是扩展(开放STV)格式感兴趣?你给出的链接是每种格式的唯一规范吗?完全公开,我写道