Python CSV数据清洗脚本:日期校验逻辑的整合问题
解决CSV清洗脚本的日期校验整合与过滤问题
核心问题分析
你遇到的两个问题本质是流程顺序错误和校验逻辑未正确嵌入写入流程:
- 写入异常:原流程先写入所有行再调用
CheckDates(),若CheckDates()需要修改输出文件,会导致文件被重复打开/操作冲突; - 日期过滤失效:校验函数未在写入前拦截无效行,或校验逻辑本身存在格式匹配错误。
解决方案:重构流程,将校验嵌入读写循环
1. 调整CleanUpData()逻辑
把日期校验和无效行剔除整合到读取-校验-写入的单循环中,避免事后修改文件:
import csv from datetime import datetime def is_invalid_row(row): # 实现你的无效行判断逻辑(比如空行、必填字段缺失) return any(not cell.strip() for cell in row[:3]) # 示例:前3列不能为空 def CheckDates(date_str): # 改为接收单个日期字符串,返回布尔值表示是否有效 if not date_str.strip(): return False # 空日期直接判定无效 try: # 替换为你的CSV实际日期格式,比如'%m/%d/%Y'对应MM/DD/YYYY datetime.strptime(date_str.strip(), '%Y-%m-%d') return True except ValueError: return False def CleanUpData(input_file, output_file): with open(input_file, 'r', newline='', encoding='utf-8') as infile, \ open(output_file, 'w', newline='', encoding='utf-8') as outfile: reader = csv.reader(infile) writer = csv.writer(outfile) # 写入表头 header = next(reader) writer.writerow(header) # 遍历处理每一行 for row_num, row in enumerate(reader, start=2): # 行号从2开始(跳过表头) # 第一步:剔除无效行 if is_invalid_row(row): print(f"第{row_num}行:无效行,已跳过") continue # 第二步:日期校验(假设日期在第4列,索引为3) date_col_index = 3 if not CheckDates(row[date_col_index]): print(f"第{row_num}行:日期格式错误,已跳过 | 日期值:{row[date_col_index]}") continue # 所有校验通过,写入文件 writer.writerow(row) # 调用示例 CleanUpData('input.csv', 'cleaned_output.csv')
2. 关键修复点
- 避免文件冲突:全程在同一个
with块内完成读写,不会出现重复打开输出文件的情况; - 前置校验:只有通过无效行判断和日期校验的行才会被写入,从源头过滤无效数据;
- 明确校验逻辑:
CheckDates()专注于单个日期的格式校验,返回明确的布尔值,便于嵌入循环判断; - 编码与换行符:添加
newline=''和指定编码,避免Windows下写入CSV出现空行的问题。
3. 调试技巧
如果仍有不符合条件的行未被过滤,按以下步骤排查:
- 打印待校验的日期值,确认是否和你预设的格式匹配(比如是
YYYY-MM-DD还是DD/MM/YYYY); - 在
CheckDates()中添加调试打印:def CheckDates(date_str): cleaned_date = date_str.strip() print(f"校验日期:{cleaned_date}") if not cleaned_date: print("空日期,判定无效") return False try: datetime.strptime(cleaned_date, '%Y-%m-%d') print("日期格式有效") return True except ValueError as e: print(f"日期格式错误:{e}") return False - 确认日期列的索引是否正确(CSV表头不算入数据行,索引从0开始)。
内容的提问来源于stack exchange,提问作者Kyle Lucas
相关产品推荐
相关产品推荐

