python - 处理非常大的文件(> 90GB)

时间:2017-05-05 01:05:55

标签: python file buffer

我需要处理几个非常大的文件(每个> 90GB)。只有一小部分文件对我很重要。我想扫描文件并将必要的行写入另一个文件,因此每次运行实验时我都不需要处理这么大的文件。每行约1000个字符。

我使用以下代码:

def readFile(inputFile, outputFile):
    startDate = datetime.datetime.strptime('10/06/2010 00:00:00', '%m/%d/%Y %H:%M:%S')
    endDate = datetime.datetime.strptime('10/13/2010 23:59:59', '%m/%d/%Y %H:%M:%S')

    total_lines = 0

    with open(inputFile, 'r') as a_file:
        for a_line in a_file:   

            total_lines += 1

            id, date, content = splitLine(a_line)

            datetime_object = datetime.datetime.strptime(date, '%m/%d/%Y %H:%M:%S')

            if (datetime_object > startDate and datetime_object < endDate):
                appendToFile(outputFile, a_line)

    return total_lines

def splitLine(long_string):
    values = long_string.split(",")
    return values[0],values[1],values[2]

def appendToFile(outputFile, outputString):
    try:
        file = open(outputFile, 'a+')
        file.write(outputString)
        file.close()
    except Exception as ex:
        print("Error writing to file: " + outputFile)
    return

问题是,每次运行脚本时,进程都会遇到10.000.000行左右。当我使用htop命令时,我可以看到Python在卡住时仅使用大约8GB的RAM,并且使用的虚拟内存不断增加,然后操作系统会在一段时间后终止该进程。

我使用了不同的文件,也使用了Python 2.7和3.5。我也尝试使用with open(inputFile, 'r', 16777216)来使用缓冲,但结果没有改变。我在macOS Sierra 10.12.4上运行代码,机器有16GB的RAM。

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

分段打开文件,直到找到所需内容。像这样:

f = open('yourfile')

piece = f.read(4096)
while piece:
    # Implementation for each piece
    piece = f.read(4096)
f.close()

答案 1 :(得分:0)

更有效的方法是从python调用Unix awk命令。这适用于Mac和unix。

你可以像这样从python调用unix命令:

import os
os.popen('ls -l > result.txt')

运行此示例代码将创建一个名为result.txt的文件,其中包含ls -l命令的输出。

同样,您可以使用awk扫描文件并将结果传输到另一个文件。

来自awk的手册页:

  

AWK

     

NAME         awk - 模式导向的扫描和处理语言

     

概要

  awk [ -F fs ] [ -v var=value ] [ 'prog' | -f progfile ] [ file ...  ]
     

描述:

     

Awk扫描每个输入文件,查找与prog中指定的一组模式或指定为-f progfile的一个或多个文件中的任何一个模式匹配的行。对于每个模式,可以存在当文件的行与模式匹配时将执行的相关动作。每条线都匹配   反对每个模式 - 行动声明的模式部分;对每个匹配的模式执行相关的动作。文件名 - 表示标准输入。任何形式为var = value的文件都被视为赋值,而不是文件名,如果它是文件名,则在它打开时执行。选项-v后跟var = value是在执行prog之前要完成的赋值;可能存在任意数量的-v选项。 -F fs选项将输入字段分隔符定义为正则表达式fs。

阅读此答案https://unix.stackexchange.com/questions/76805/read-log-file-between-two-dates,了解如何使用awk在两个日期之间读取日志文件。