Python - 最有效地覆盖 CSV 文件中的特定行
Python - Most efficient to overwrite a specific row in a CSV file
给定以下 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 似乎不是最有效的方法,尤其是对于大文件:
- 找到匹配项后,我们继续阅读到最后。
- 我们必须逐行重写。
- 写第二个文件不太实用,存储也不实用
高效。
我写了第二段代码似乎可以解决这两个问题:
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 :如果我不想使用填充,我显然有义务阅读和重写所有内容。
一个可能的解决方案是类似数据库的解决方案,我会在未来考虑它。
如果我必须在这 2 个解决方案之间做出选择,哪一个是性能最好的?
由于行中的字符可能不同,我要么必须 read/write 整个文件,要么;正如 @tobias_k 所说,使用 seek() 回到行首并且:
- 如果行比较短,只写行和空格;
- 如果长度相同,只写一行;
- 如果它更长,请重写该行和以下内容。
我想避免使用填充,所以我使用 time.perf_counter() 来测量两个代码的执行时间,第二个解决方案似乎(几乎 2*)更快(10 000 行的 CSV,在第 6 000 行匹配)。
一种替代方法是迁移到关系数据库。
给定以下 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 似乎不是最有效的方法,尤其是对于大文件:
- 找到匹配项后,我们继续阅读到最后。
- 我们必须逐行重写。
- 写第二个文件不太实用,存储也不实用 高效。
我写了第二段代码似乎可以解决这两个问题:
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 :如果我不想使用填充,我显然有义务阅读和重写所有内容。 一个可能的解决方案是类似数据库的解决方案,我会在未来考虑它。
如果我必须在这 2 个解决方案之间做出选择,哪一个是性能最好的?
由于行中的字符可能不同,我要么必须 read/write 整个文件,要么;正如 @tobias_k 所说,使用 seek() 回到行首并且:
- 如果行比较短,只写行和空格;
- 如果长度相同,只写一行;
- 如果它更长,请重写该行和以下内容。
我想避免使用填充,所以我使用 time.perf_counter() 来测量两个代码的执行时间,第二个解决方案似乎(几乎 2*)更快(10 000 行的 CSV,在第 6 000 行匹配)。
一种替代方法是迁移到关系数据库。