读取文件夹多CSV并按规则拆分输出的代码问题(非Pandas)
问题分析与代码修正
咱们来一步步拆解你代码里的问题,然后给出修复后的版本:
核心错误点
1. 判断逻辑放错位置,仅处理最后一行
你把子集的判断代码放在了for line in cr循环的外面,这意味着只有每个输入文件的最后一行会被判断是否写入子集文件,前面的所有行都被跳过了判断,这是最致命的问题。
2. 子集的筛选逻辑完全写反了
subset_1.csv要求存储Column1以'80B'开头的记录,但你写的条件是line[0][:3] != "80B",刚好反过来了;subset_2.csv要求的是Column1不以'80B'开头 且 第4个字符不为'D',但你的条件是(line[0][:3] == "80B") and (line[0][3:4] == "D"),逻辑完全不符合需求。
3. 表头重复写入问题
你手动写入了一次表头,但注释掉了next(cr),导致每个输入文件的表头都会被写入all.csv,最终all.csv里会有多个重复的表头。另外,手动写表头不够灵活,如果输入文件的表头有变化,代码就会出错,最好直接读取输入文件的表头来复用。
修正后的代码
import glob import csv import os path = r'C:\myfolder\test' all_files = glob.glob(os.path.join(path, "*.csv")) # 定义输出文件路径 output_paths = { "all": r'C:\myfolder\all.csv', "subset1": r'C:\myfolder\subset_1.csv', "subset2": r'C:\myfolder\subset_2.csv' } # 初始化写入器和表头标记 writers = {} header_written = {key: False for key in output_paths} with open(output_paths["all"], "w", newline='') as f_all, \ open(output_paths["subset1"], "w", newline='') as f_sub1, \ open(output_paths["subset2"], "w", newline='') as f_sub2: # 创建CSV写入器 writers["all"] = csv.writer(f_all, delimiter=";", quoting=csv.QUOTE_MINIMAL) writers["subset1"] = csv.writer(f_sub1, delimiter=";", quoting=csv.QUOTE_MINIMAL) writers["subset2"] = csv.writer(f_sub2, delimiter=";", quoting=csv.QUOTE_MINIMAL) for filename in all_files: with open(filename, newline='') as infile: cr = csv.reader(infile, delimiter=";") header = next(cr) # 读取输入文件的表头 # 仅在每个输出文件第一次写入时写入表头 for key in header_written: if not header_written[key]: writers[key].writerow(header) header_written[key] = True # 逐行处理记录 for line in cr: # 写入all.csv writers["all"].writerow(line) # 判断subset1的条件:Column1以'80B'开头 if line[0].startswith('80B'): writers["subset1"].writerow(line) # 判断subset2的条件:Column1不以'80B'开头 且 第4个字符不是'D' # 注意:要确保Column1长度至少为4,避免索引越界 if not line[0].startswith('80B') and (len(line[0]) <4 or line[0][3] != 'D'): writers["subset2"].writerow(line)
修正说明
- 表头处理:通过
next(cr)读取输入文件的表头,用header_written标记来确保每个输出文件只写入一次表头,既避免重复,又适配输入文件的表头结构; - 判断逻辑位置:把子集的判断放在
for line in cr循环内部,确保每一行都被检查; - 修正筛选逻辑:
subset1使用startswith('80B')更直观准确;subset2修正为符合需求的逻辑,同时增加了len(line[0]) <4的判断,避免当Column1长度不足4时出现索引越界错误;
- 代码结构优化:用字典管理输出路径和写入器,让代码更整洁易维护。
内容的提问来源于stack exchange,提问作者PSt
相关产品推荐
相关产品推荐

