【问题标题】:Performance issue when parsing a large file line by line逐行解析大文件时的性能问题
【发布时间】:2019-01-11 02:32:32
【问题描述】:

我有一组数百万个小数存储在一个文件中

我编写了一个 Python 脚本,它逐行从制表符分隔的文本文件中读取数字,计算提醒并将结果附加到输出文件中。由于某种原因,它消耗了大量内存(Ubuntu 上 20 Gb 的内存来解析一百万个数字)。由于频繁写入,它还会冻结系统。

调整此脚本的正确方法是什么。

import os
import re

my_path = '/media/me/mSata/res/'
# output_file.open() before the first loop didn't help

for file_id in range (10,11): #10,201
    filename = my_path + "in" + str(file_id) + ".txt"

    fstr0 = ""+my_path +"out"+ str(file_id)+"_0.log"
    fstr1 = ""+my_path +"res"+ str(file_id)+"_1.log"

    with open(filename) as fp:
        stats = [0] * (512)

        line = fp.readline()

        while line:
            raw_line = line.strip()
            arr_of_parsed_numbers = re.split(r'\t+', raw_line.rstrip('\t'))

            for num_index in range(0, len(arr_of_parsed_numbers)):
                my_number = int(arr_of_parsed_numbers[num_index])

                v0 = (my_number % 257) -1     #value 257 is correct
                my_number = (my_number )//257   
                stats[v0] += 1
                v1 = my_number % 256
                stats[256+v1]+=1

                f0 = open(fstr0, "a")
                f1 = open(fstr1, "a")

                f0.write("{}\n".format(str(v0).rjust(3)))
                f1.write("{}\n".format(str(v1).rjust(3)))
                f0.close()
                f1.close() 

            line=fp.readLine()

    print(stats)

# tried output_file.close() here as well
print("done")

更新: 我已经在 Windows 10(Python.exe 中的 10 Mb 内存)和 Ubuntu(消耗了 10 Gb 内存)下运行了这个脚本。什么会导致这种差异?一千倍是很多。

他的脚本在 Windows 10 上消耗了大约 20Mb(看起来 o

【问题讨论】:

  • 如果你执行f0 = open(fstr0, "a") 一百万次,你的程序会很慢。
  • 而不是打开和关闭整个输入文件中每一行中每个数字的输出文件(fstr0,fstr1),尝试在开始之前打开它们一次,并在整个结束时关闭它们解析
  • 其余的计算可能可以优化,但很可能会足够快
  • while line: 循环如何停止?
  • 您的内存不足,因为您很可能有一个无限循环。

标签: python performance


【解决方案1】:

试试这样的。请注意,每个文件只打开和关闭一次,并且循环每行迭代一次。

import os
import re

my_path = '/media/me/mSata/res/'
# output_file.open() before the first loop didn't help

for file_id in range (10,11): #10,201
    filename = my_path + "in" + str(file_id) + ".txt"

    fstr0 = ""+my_path +"out"+ str(file_id)+"_0.log"
    fstr1 = ""+my_path +"res"+ str(file_id)+"_1.log"

    with open(filename, "r") as fp, open(fstr0, "a") as f0, open(fstr1, "a") as f1:
        stats = [0] * (512)

        for line in fp:
            raw_line = line.strip()
            arr_of_parsed_numbers = re.split(r'\t+', raw_line.rstrip('\t'))

            for num_index in range(0, len(arr_of_parsed_numbers)):
                my_number = int(arr_of_parsed_numbers[num_index])

                v0 = (my_number % 257) -1     #value 257 is correct
                my_number = (my_number )//257   
                stats[v0] += 1
                v1 = my_number % 256
                stats[256+v1]+=1

                f0.write("{}\n".format(str(v0).rjust(3)))
                f1.write("{}\n".format(str(v1).rjust(3)))

    print(stats)

# tried output_file.close() here as well
print("done")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-04
    • 2011-12-05
    • 2014-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-24
    • 2019-10-29
    相关资源
    最近更新 更多