Python-最有效的方式来覆盖CSV文件中的特定行

时间:2019-02-28 12:13:21

标签: python csv row python-3.7

给出以下csv文件:

01;blue;brown;black
02;glass;rock;paper
03;pigeon;squirel;shark

我的目标是在第一个病房中替换包含“ 02”的(唯一)行。

我写了这段代码:

with open("csv", 'r+', newline='', encoding='utf-8') as csvfile, open('csvout', 'w', newline='', encoding='utf-8') as out:
    reader = csv.reader(csvfile, delimiter=';')
    writer = csv.writer(out, delimiter=';')
    for row in reader:
        if row[0] != '02':
            writer.writerow(row)
        else:
            writer.writerow(['02', 'A', 'B', 'C'])

但是,以另一种方式重写整个CSV似乎并不是最有效的处理方式,尤其是对于大文件:

  1. 找到匹配项后,我们会继续阅读直至结尾。
  2. 我们必须一步一步地重写每一行。
  3. 写第二个文件不是很实际,存储也不是很容易 高效。

我写了第二段代码,似乎可以回答这两个问题:

with open("csv", 'r+', newline='', encoding='utf-8') as csvfile:
    content = csvfile.readlines()
    for index, row in enumerate(content):
        row = row.split(';')
        if row[2] == 'rock':
            tochange = index
            break
    content.pop(tochange)
    content.insert(tochange, '02;A;B;C\n')
    content = "".join(content)
    csvfile.seek(0)
    csvfile.truncate(0)     # Erase content
    csvfile.write(content)

您是否同意第二种解决方案更有效? 您有任何改进或更好的方法吗?

编辑:该行中的字符数可以变化。

编辑2 :如果我不想使用填充,显然我必须阅读和重写所有内容。 可能的解决方案是类似数据库的解决方案,我将在以后考虑。

如果我必须在这两种解决方案之间进行选择,那么哪种才是性能最佳的解决方案?

1 个答案:

答案 0 :(得分:1)

由于该行中的角色可能有所不同,我要么必须读/写整个文件,要么;如@tobias_k所述,请使用seek()返回该行的开头,然后:

  • 如果行短,则只写行并用空格填充;
  • 如果长度相同,则只写一行;
  • 如果需要更长的时间,请重写该行以及以下内容。

我想避免使用填充,所以我使用time.perf_counter()来测量两个代码的执行时间,并且第二种解决方案似乎快了(几乎2 *)(CSV为10 000行,在第6 000个匹配)。

一种选择是迁移到关系数据库