Python CSV操作:执行writerows后能否直接修改并执行writerow?
CSV单函数内实现插入行与追加列的问题
我需要修改CSV文件,实现两个操作:插入指定行,同时为所有行追加用户选择的额外列(时间戳、文件名、唯一ID等)。但尝试时发现,执行output.writerows(rows)插入行后,后续循环处理追加列的逻辑完全失效;注释掉该语句后循环能正常运行,保留则会跳过写入的内容。
想请教:
- 能否在单个函数内完成插入行+追加列的操作?
- 是否必须先保存文件,重新打开后再追加列?
我的目标是让用户选择要追加的内容,最终将修改后的文件保存到新位置,已尝试多种方法一周仍未解决。
示例代码
import csv import itertools import uuid from datetime import datetime rows = [[1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2]] def _sanitize_report(source_file, dest_file, append_timestamp, timestamp_format, append_filename, file, append_id): with open(source_file, 'r') as report: reader = csv.reader(report) with open(dest_file, 'w') as output_file: data_rows = 0 output = csv.writer(output_file) output.writerows(rows) for index, row in enumerate(reader): if append_timestamp and append_filename and append_id: output.writerow(itertools.chain([datetime.today().strftime(timestamp_format)], [str(file).replace(file[0:3], '')], [uuid.uuid4()])) elif append_timestamp and append_filename: output.writerow(itertools.chain([datetime.today().strftime(timestamp_format)], [str(file).replace(file[0:3], '')])) elif append_timestamp and append_id: output.writerow(itertools.chain([datetime.today().strftime(timestamp_format)], [uuid.uuid4()])) elif append_filename and append_id: output.writerow(itertools.chain([str(file).replace(file[0:3], '')], [uuid.uuid4()])) elif append_timestamp: output.writerow(itertools.chain( [datetime.today().strftime(timestamp_format)])) elif append_filename: output.writerow(itertools.chain([str(file).replace(file[0:3], '')])) elif append_id: output.writerow(itertools.chain([uuid.uuid4()])) else: output.writerow([value.replace('(not set)', '') for value in row]) data_rows += 1 _sanitize_report('test.csv', 'test_' + str(uuid.uuid4()) + '.csv', append_timestamp=True, timestamp_format=datetime.utcnow().isoformat() + 'Z', append_filename=True, file='123Test_success', append_id=True)
问题分析
你的代码逻辑存在两个核心问题:
- 写入逻辑错误:
output.writerows(rows)写入自定义行后,后续循环遍历原文件的reader,执行output.writerow(...)是单独写入新行(而非给已写入的行追加列),这和你“追加额外列”的需求不符。 - 数据处理顺序混乱:你没有将插入的
rows和原文件的行统一处理,而是分开写入,导致后续的追加逻辑无法作用到插入的行上。
解决方案:单函数内完成所有操作
完全不需要拆分操作,只需先统一处理所有数据(插入行+追加列),再一次性写入文件。修改后的代码如下:
import csv import uuid from datetime import datetime rows = [[1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2], [1000000, 'Test', 'Test', 179, 1111, 222, 5, 'Test', 'Test', 1111, 'Test', 222, 'Test', 1111, 22222, 'Test', '', 1, 2]] def _sanitize_report(source_file, dest_file, append_timestamp, timestamp_format, append_filename, file, append_id): # 1. 读取原文件所有行 with open(source_file, 'r') as report: reader = csv.reader(report) original_rows = list(reader) # 2. 合并插入行与原文件行(可根据需求调整顺序,比如插在末尾或中间) all_rows = rows + original_rows # 3. 生成要追加的额外字段 extra_fields = [] if append_timestamp: extra_fields.append(datetime.today().strftime(timestamp_format)) if append_filename: extra_fields.append(str(file).replace(file[0:3], '')) if append_id: extra_fields.append(str(uuid.uuid4())) # 4. 处理所有行:追加字段 + 清理内容 processed_rows = [] for row in all_rows: # 清理原内容中的'(not set)' cleaned_row = [value.replace('(not set)', '') for value in row] # 追加额外字段到行末尾 cleaned_row.extend(extra_fields) processed_rows.append(cleaned_row) # 5. 一次性写入所有处理后的行 with open(dest_file, 'w', newline='') as output_file: output = csv.writer(output_file) output.writerows(processed_rows) print(f"处理完成,共写入 {len(processed_rows)} 行") _sanitize_report('test.csv', 'test_' + str(uuid.uuid4()) + '.csv', append_timestamp=True, timestamp_format=datetime.utcnow().isoformat() + 'Z', append_filename=True, file='123Test_success', append_id=True)
关键改进点
- 统一数据处理:先将插入的
rows和原文件的行合并,再批量处理每一行,避免分阶段写入的逻辑混乱。 - 正确追加列:使用
extend()将额外字段添加到每一行的末尾,真正实现“追加列”的效果。 - 简化逻辑:将生成额外字段的逻辑提前,避免重复的条件判断,代码更简洁易维护。
- 文件操作优化:只打开两次文件(一次读原文件,一次写新文件),避免嵌套文件操作的潜在问题。
补充说明
如果你需要将插入的行放在原文件行的中间或其他位置,只需调整all_rows = rows + original_rows这一行的拼接逻辑即可,比如all_rows = original_rows[:5] + rows + original_rows[5:]表示将插入行放在原文件第5行之后。
内容的提问来源于stack exchange,提问作者Maykid
相关产品推荐
相关产品推荐

