如何使用csv DictWriter为同程序已生成的现有CSV新增两列
基于csv.DictWriter为现有CSV追加两列的实现方案
原代码的核心逻辑偏差
- 输出文件路径存在笔误:文件名前多了一个左括号,实际写入的文件名为
(Infusion_final{zip_add}.csv,不符合预期的输出路径 - 输出文件采用
a+追加模式打开,没有把原CSV的已有内容读出、和新增字段拼接后重写,仅单独将新增两列的内容写入文件,最终自然只能得到仅含新增列的文件 - DictWriter初始化时只传入了新增两列的字段名,没有将原CSV的已有列名纳入fieldnames配置,从写入逻辑上就无法保留原有列内容
- 读写循环层级错位:读取原CSV、逐行写入的逻辑被放在med与spec的迭代循环内部,每处理一对新增值就完整遍历一遍原CSV,会完全打乱原有行和新增值的对应关系
- 无效行操作:
row.append(w.writerow(dict2))无实际作用,writerow是直接向文件流写入数据,不会返回可拼接的行对象,对读取到的原row列表做append操作不会影响最终文件内容 - 文件流生命周期错位:原CSV和输出文件的打开操作被放在单对med、sp的循环内部,每轮循环都会重新开关文件,反复读写会造成内容损坏
正确实现流程
- 一次性读取原CSV的全部内容,提取原有表头
- 将原有表头与需要新增的
Medicines、Specialities两个字段拼接,组成DictWriter需要的完整fieldnames列表 - 校验
meds、specs的长度和原CSV的数据行长度一致,保证每行新增值和原数据行一一对应,避免错位 - 打开目标输出文件,写入完整表头后逐行遍历原数据,为每行补充对应索引的新增字段值,再通过DictWriter写入文件
参考实现代码
import csv origin_rows = [] origin_header = [] # 一次性读取原CSV全部内容 with open(f'Infusion_t{zip_add}.csv', 'r', encoding='utf-8-sig') as read_f: reader = csv.reader(read_f) for line_idx, row in enumerate(reader): # 提取表头 if line_idx == 0: origin_header = row continue origin_rows.append(row) # 校验数据长度匹配 if len(meds) != len(origin_rows) or len(specs) != len(origin_rows): raise ValueError("新增字段行数与原CSV数据行数不匹配,无法对应写入") # 拼接完整字段列表 full_fieldnames = origin_header + ["Medicines", "Specialities"] # 写入合并后的完整CSV文件 with open(f'Infusion_final{zip_add}.csv', 'w', encoding='utf-8-sig', newline='') as write_f: # 初始化DictWriter,传入全量字段名 writer = csv.DictWriter(write_f, fieldnames=full_fieldnames) writer.writeheader() # 逐行写入合并后的数据 for row_idx, row_data in enumerate(origin_rows): # 将原行数据转为字典格式,匹配字段名 row_dict = {col_name: col_val for col_name, col_val in zip(full_fieldnames[:len(origin_header)], row_data)} # 补充新增字段值 row_dict["Medicines"] = meds[row_idx].text row_dict["Specialities"] = specs[row_idx].text writer.writerow(row_dict)
实操提示:如果后续需要多次给同一CSV追加列,只要保留全量字段的映射关系,每次写入时补充对应字段的值即可,无需重复解析全量文件内容。
内容的提问来源于stack exchange,提问作者Abhishek Rai
相关产品推荐
相关产品推荐

