JSON转PSV时Python去重功能失效问题求助
我在将JSON文件转换为PSV(竖线分隔文件)时,尝试通过配置文件指定规则去重,但去重功能未生效。以下是实现流程的Python代码,请协助排查问题:
import json import sys import csv from datetime import datetime, timedelta # function to convert datetime format def convert_datetime(dt, dt_type): if dt_type == 'd': return datetime.strptime(dt[:19], '%Y-%m-%dT%H:%M:%S').strftime('%Y-%m-%d') elif dt_type == 'fd': return datetime.strptime(dt[:23], '%Y-%m-%dT%H:%M:%S.%f').strftime('%Y-%m-%d-%H.%M.%S.%f') # function to delete duplicates based on specified fields def delete_duplicate(data, config): # sort data based on dupvalue field in descending order data.sort(key=lambda x: x[config['dupvalue']], reverse=True) unique_data = [] unique_keys = set() for d in data: key = tuple(d[field] for field in config['fields']) if key not in unique_keys: unique_data.append(d) unique_keys.add(key) return unique_data # read config file with open(sys.argv[2]) as f: config = {} for line in f: field, value, dt = line.strip().split('|') config[field] = value config[field + '_dt'] = dt # read data from json file with open(sys.argv[1]) as f: data = json.load(f) # extract fields from data fields = config['fields'] = data[0].keys() # convert datetime fields for row in data: for field in fields: if field + '_dt' in config: row[field] = convert_datetime(row[field], config[field + '_dt']) # delete duplicates data = delete_duplicate(data, config) # write data to pipe separated file with open(sys.argv[3], 'w') as f: writer = csv.writer(f, delimiter='|') writer.writerow(fields) for row in data: writer.writerow([row.get(field, 'null') for field in fields]) # add header and tail record with count of data to file with open(sys.argv[3], 'r') as f: lines = f.readlines() with open(sys.argv[3], 'w') as f: f.write('HEADER|{}|{}|{}\n'.format(len(fields), len(data), datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) f.writelines(lines) f.write('TAIL|{}|{}|{}\n'.format(len(fields), len(data), datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
核心问题分析
配置指定的去重字段被强制覆盖:代码先读取配置文件,随后执行
config['fields'] = data[0].keys(),直接把配置里定义的去重字段替换成了JSON数据的所有字段。导致delete_duplicate函数用所有字段生成去重键,而非预期的配置指定字段,自然无法按规则去重。dupvalue字段可能未正确配置:delete_duplicate函数依赖config['dupvalue']字段排序来保留优先级最高的记录,如果配置文件未设置该键,或该字段在JSON数据中不存在,会引发KeyError,或导致排序失效,去重后保留的记录不符合预期。日期转换可能破坏去重键一致性:如果日期转换过程中出现格式错误,同一原始日期值生成不同字符串,会导致本该被判定为重复的记录因键值不同而无法去重。
修复建议
修正配置读取与字段赋值逻辑:
不要用data[0].keys()覆盖配置字段,而是从配置文件中提取指定的去重字段。假设配置文件中有一行fields|id,name|,修改配置读取代码:# read config file with open(sys.argv[2]) as f: config = {} for line in f: field, value, dt = line.strip().split('|') if field == 'fields': config[field] = value.split(',') else: config[field] = value config[field + '_dt'] = dt同时删除
fields = config['fields'] = data[0].keys(),改为:fields = config['fields']验证
dupvalue配置有效性:检查配置文件中是否正确设置了dupvalue对应的字段,且该字段在JSON数据中存在、类型可用于排序(如日期字符串、数字)。测试日期转换逻辑:确认同一原始日期值转换后生成一致的字符串,避免因转换错误导致去重键不一致。
内容的提问来源于stack exchange,提问作者sumalatha majjiga

