使用python生成器处理大型文本文件

时间:2018-04-10 11:27:01

标签: python generator large-files chunks

我是使用生成器的新手,并且已经阅读了一些内容,但需要一些帮助处理大块文本文件。我知道这个主题已被涵盖,但示例代码的解释非常有限,如果不了解正在发生的事情,很难修改代码。

我的问题很简单,我有一系列大文本文件,包含以下格式的人类基因组测序数据:

chr22   1   0
chr22   2   0
chr22   3   1
chr22   4   1
chr22   5   1
chr22   6   2

文件的长度介于1Gb和〜20Gb之间,这个文件太大而无法读入RAM。因此,我想一次读取10000行的块/行中的行,以便我可以对这些仓大小的最后一列执行计算。

根据此链接here,我写了以下内容:

def read_large_file(file_object):
    """A generator function to read a large file lazily."""

    bin_size=5000
    start=0
    end=start+bin_size

    # Read a block from the file: data
    while True:
        data = file_object.readlines(end) 
        if not data:
            break
        start=start+bin_size
        end=end+bin_size
        yield data


def process_file(path):

    try:
        # Open a connection to the file
        with open(path) as file_handler:
            # Create a generator object for the file: gen_file
            for block in read_large_file(file_handler):
                print(block)
                # process block

    except (IOError, OSError):
        print("Error opening / processing file")    
    return    

if __name__ == '__main__':
            path='C:/path_to/input.txt'
    process_file(path)

在'process_block'中我期望返回的'block'对象是10000个元素的列表,但不是吗?第一个列表是843个元素。第二个是2394个元素?

我想在一个街区中找回'N'个行,但我对此处发生的事情感到非常困惑?

此解决方案here似乎可以提供帮助,但我又不知道如何修改它以一次读取N行?

这个here看起来也是一个非常好的解决方案,但是,我没有足够的背景说明来理解修改代码。

真的很感激任何帮助吗?

4 个答案:

答案 0 :(得分:4)

不要在文件中使用偏移量,而是尝试从循环中构建并生成10000个元素的列表:

x                 y            attributes1            attributes2
Location         People     ['USA', 'UK', 'Brazil']    ['Mohit', 'Aryan']
People           College    ['Mohit', 'Aryan', 'Tom']  ['Havard', 'Oxford']

答案 1 :(得分:2)

10000不是要读取的行数,而是从文件中读取的近似字节数。

答案 2 :(得分:1)

不是一个正确的答案,但找出这种行为的原因大约需要27秒:

(blook)bruno@bigb:~/Work/blookup/src/project$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
pythonrc start
pythonrc done
>>> help(file.readlines)

Help on method_descriptor:

readlines(...)
    readlines([size]) -> list of strings, each a line from the file.

    Call readline() repeatedly and return a list of the lines so read.
    The optional size argument, if given, is an approximate bound on the
    total number of bytes in the lines returned.

据我所知,并非所有人都是专业程序员 - 当然,文档并不总是足以解决问题(我很乐意回答这些问题),但实际上是数字在文档开头用简单的字母写答案的问题变得有点烦人。

答案 3 :(得分:0)

如果它能帮助其他遇到类似问题的人是基于here

的解决方案
import pandas as pd

def process_file(path,binSize):

    for chunk in pd.read_csv(path, sep='\t', chunksize=binSize):
        print(chunk)
        print(chunk.ix[:,2]) # get 3rd col
        # Do something with chunk....  

if __name__ == '__main__':
    path='path_to/infile.txt'
    binSize=5000
    process_file(path,binSize)