【问题标题】:Inconsistent loop execution times with large memory processing大内存处理的循环执行时间不一致
【发布时间】:2020-04-10 21:25:23
【问题描述】:

我有许多大型 csv 文件(每个约 400 MB,需要处理数千个,每个程序执行至少一百个)在每行的第一个单元格中包含长字符串(每行大约 100-300 个字符 1每个文件百万行),我的 Python 程序检查子字符串是否在给定的字符串中。如果是这样,那么我将包含该字符串的行附加到一个列表中,以便在处理完所有输入文件后存储在另一个系列的 csv 文件中。对于前十几个输入文件,程序以每个文件大约 20 秒的速度运行,我对此感到满意。

代码的相关部分(字符串处理循环)如下所示:

check = set(['a','b','c'])
storage = []
data = glob.glob('data_address/*.csv')
for raw_file in data:
    read_file = open(raw_file,'r',newline='',encoding='utf-8')  
    list_file = list(csv.reader((line.replace('\0','') for line in read_file), delimiter=","))
    row_count = sum(1 for row in list_file)

    for i in range(1, row_count);
        text = set(list_file[i][0].split())
        if len(check.intersection(text)) > 0:
           storage.append(list_file[i])

问题是随着处理的输入文件数量的增加,我开始有某些文件需要超过 20 秒的时间。此外,处理这些异常需要的时间越来越长——第一个异常需要大约 50 秒来处理,在循环结束时,异常可能需要数千秒来处理,这表明问题出在循环本身而不是任何个人档案。就字符串匹配的数量而言,这些异常与其他文件没有明显不同。

我不明白的是处理时间的增加并不一致。在每个异常之间我仍然有很多 20 秒的文件,所以不能说程序只是随着内存存储的增加而变慢。有谁知道发生了什么? cProfile 无法显示任何可能导致问题的组件。

我在 Windows 10 上使用 64 位 Python 3.8 和 1TB 硬盘,大约 10,000 MB 活动内存。

【问题讨论】:

  • @barny 感谢您的反馈。我已经相应地编辑了我的帖子。
  • 在您共享的代码中,您并没有关闭文件。你真的应该使用上下文管理器,它们很棒。你能提供一个minimal reproducible example吗?我可以看到一些可以重构的东西,但是当我无法运行代码时很难做到。此外,虽然它可能无法解释手头的特定问题,但此代码存在许多低效方面。
  • 这是使用 csv 的一种相当不寻常的方式。您是否尝试过更传统的方法?查看文档docs.python.org/3/library/csv.html。但如果是特定文件有问题,那么通用代码不是问题:,这些文件有什么不同?
  • 某人,显然是“上帝”,删除了我的评论:展示自己,“上帝”:你为什么这样做?
  • @amc 虽然我同意 OP 应该使用with,但当read_file 被分配一个新的打开文件时,文件将在每次循环中关闭。更可能的问题是,list_file 被存储引用,这只会增加内存使用量。

标签: python performance loops debugging memory


【解决方案1】:

我们还没有足够的信息来正确诊断问题,因此我想我会尝试改进您共享的代码:

import csv
import pathlib

check = {'a', 'b', 'c'}

data_path = pathlib.Path("data_address")

saved_rows = []

for curr_path in data_path.glob("*.csv"):
    with open(curr_path, newline='') as curr_file:
        reader = csv.reader((line.replace('\0', '') for line in curr_file), delimiter=",")

        for row in reader:
            row_text = row[0].split()
            if any(elem in check for elem in row_text):
                saved_rows.append(row)

虽然我无法对其进行测试,但它应该可以正常工作。

【讨论】:

  • 谢谢!效果很好,实际上解决了我的问题!现在,我在整个过程中每个文件大约 20 秒。
  • @pythonuser 在出现性能问题之前,您从迭代中得到了什么,对吧?所以现在是 20 多岁的常数?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-20
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多