在Python中高效地解析大型文本文件?

在Python中高效地解析大型文本文件?,python,file-io,text-processing,Python,File Io,Text Processing,我有一系列大而扁平的文本文件需要解析,以便插入到SQL数据库中。每条记录跨越多行,由大约一百个固定长度的字段组成。我试图找出如何在不将整个文件加载到内存的情况下有效地解析它们 每条记录以数字“1”开头,作为新行的第一个字符(尽管并非每一行以“1”开头都是新记录),随后以一系列20个空格结束许多行。虽然每个字段的宽度固定,但每个记录的长度可变,因为它可能包含也可能不包含几个可选字段。所以我一直在使用“…20个空格…\n1”作为记录分隔符 我一直在尝试使用类似这样的方法来一次处理1kb: def r

我有一系列大而扁平的文本文件需要解析,以便插入到SQL数据库中。每条记录跨越多行,由大约一百个固定长度的字段组成。我试图找出如何在不将整个文件加载到内存的情况下有效地解析它们

每条记录以数字“1”开头,作为新行的第一个字符(尽管并非每一行以“1”开头都是新记录),随后以一系列20个空格结束许多行。虽然每个字段的宽度固定,但每个记录的长度可变,因为它可能包含也可能不包含几个可选字段。所以我一直在使用
“…20个空格…\n1”
作为记录分隔符

我一直在尝试使用类似这样的方法来一次处理1kb:

def read_in_chunks(file_object, chunk_size):
    while True:
        data = file_object.read(chunk_size)
        if not data:
            break
        yield data

file = open('test.txt')
for piece in read_in_chunks(file, chunk_size=1024):
   # Do stuff
然而,我遇到的问题是当一条记录跨越多个数据块时。我是否忽略了一个明显的设计模式?这个问题似乎有点普遍。谢谢

def recordsFromFile(inputFile):
    record = ''
    terminator = ' ' * 20
    for line in inputFile:
        if line.startswith('1') and record.endswith(terminator):
            yield record
            record = ''
        record += line
    yield record

inputFile = open('test.txt')
for record in recordsFromFile(inputFile):
    # Do stuff

顺便说一句,
文件
是一个内置函数。更改其值是一种糟糕的风格。

好的,我重新阅读了这个问题…为什么不将文件作为一个通读来解析一次,以获取所有记录的记录结束位置…然后通过将这些值反馈到块中来返回size@aking1012:谢谢。这就是我写这个问题以来一直在使用的方法。然而,一次读取一个字节会花费很长时间,而且一次读取多个字节仍然会给我带来跨多个数据块的问题。我确信有一个显而易见的解决方案就在我面前。是的,若你们一次读两段,那个么问题就解决了。在C语言中,它将被实现为一个循环缓冲区。除了读取两个块并将其用于python之外,我还没有见过快速循环缓冲区实现。如果一次使用两个数据块,使用rstrip/lstrip并获得大小差异可能是有效的……但我还没有对其进行负载测试。如果一条记录可能比单个数据块长,那么两个数据块也不起作用。从块的最后一个字节开始的1026字节记录将完全跨越下一个块以及第三个块的第一个字节。但无论如何,读取1024字节块的文件都是愚蠢的,除非您的系统内存非常少。@robmayoff如果您只查找终止点……记录大小不再重要……终止符的大小才重要。然后将块大小调整为内存大小。只是我的意见。关于文件有多大的问题,当我听说大型平面文本文件迁移到sql时,我认为拥有大量GB文件的金融机构使用列表和结尾处的“”。join()来构建字符串稍微更有效。我喜欢它,但如果它是一个大文件,这不是会将大量数据加载到内存中吗?我不这么认为。你认为为什么会这样?如果是这样的话,这会是一个问题吗?输入文件有多大?它最多只能在内存中加载一条记录。Python的文件迭代器非常容易使用,并且相对高效,特别是在内存方面。我喜欢
yield
,它让事情变得非常简单