别再手动改格式了!Python处理JSONL文件的3种实战场景与完整代码(含编码避坑)

别再手动改格式了!Python处理JSONL文件的3种实战场景与完整代码(含编码避坑) Python实战JSONL文件高效处理的3个进阶场景与避坑指南JSONLJSON Lines格式因其行存储特性在数据处理、日志分析和AI模型训练中广泛应用。但实际工作中开发者常会遇到编码混乱、多值处理和结构转换等棘手问题。本文将分享三个真实场景下的解决方案附带可直接复用的代码模板。1. 编码问题当UTF-8遇到GBK时的终极解法某次处理用户行为日志时我遇到了这样的报错UnicodeDecodeError: gbk codec cant decode byte 0x80 in position 32: illegal multibyte sequence1.1 自动检测编码的最佳实践与其猜测文件编码不如用chardet自动检测import chardet def detect_encoding(file_path): with open(file_path, rb) as f: rawdata f.read(10000) # 读取前1万字节用于检测 return chardet.detect(rawdata)[encoding]1.2 安全读取混合编码文件对于可能包含混合编码的文件建议使用错误处理机制def safe_read_jsonl(file_path): encodings [utf-8, gb18030, latin1] # 按优先级尝试 for enc in encodings: try: with open(file_path, r, encodingenc) as f: return [json.loads(line) for line in f] except UnicodeDecodeError: continue raise ValueError(无法解码文件)关键提示处理中文文本时优先尝试gb18030而非gbk前者是后者的超集2. 多值处理拆分AI模型输出的复合答案当处理类似太平洋, 大西洋, 印度洋这样的多值字段时常规方法会失效。以下是优化方案2.1 智能分割算法def smart_split(text): # 处理常见分隔符中文逗号、英文逗号、分号等 separators [, ,, ;, , 、] for sep in separators: if sep in text: return [item.strip() for item in text.split(sep) if item.strip()] return [text]2.2 保留原始结构的转换def convert_multi_value(jsonl_file, output_file): results [] with open(jsonl_file, r, encodingutf-8) as f: for line in f: data json.loads(line) for key, value in data.items(): if isinstance(value, str) and any(sep in value for sep in [,, ]): data[key] smart_split(value) results.append(data) with open(output_file, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2)3. 结构转换从JSONL到前端友好格式3.1 转换为嵌套字典适用于需要快速查找的场景def jsonl_to_nested_dict(input_file): result {} with open(input_file, r, encodingutf-8) as f: for line in f: item json.loads(line) # 假设每行是{id: xxx, data: {...}}格式 result[item[id]] item[data] return result3.2 转换为带元数据的数组更适合API返回def jsonl_to_enhanced_array(input_file): return [ {**json.loads(line), _meta: {length: len(line)}} for line in open(input_file, r, encodingutf-8) ]4. 性能优化处理超大JSONL文件的技巧当文件超过1GB时内存优化变得至关重要4.1 流式处理方案def process_large_file(input_path, output_path): with open(input_path, r, encodingutf-8) as fin, \ open(output_path, w, encodingutf-8) as fout: for line in fin: try: data json.loads(line) # 在此处添加处理逻辑 fout.write(json.dumps(data) \n) except json.JSONDecodeError as e: print(f解析失败的行: {line[:50]}...)4.2 并行处理加速from multiprocessing import Pool def parallel_process(jsonl_file, worker_func, processes4): with Pool(processes) as pool: with open(jsonl_file, r, encodingutf-8) as f: results pool.map(worker_func, f) return results实战中的经验之谈始终指定编码即使文件声称是UTF-8也可能会混入特殊字符验证每行JSON使用json.loads()比eval()更安全保留处理日志记录跳过的错误行便于后续排查内存监控处理大文件时添加内存检查逻辑import psutil def memory_safe_operation(): if psutil.virtual_memory().available 100 * 1024 * 1024: # 小于100MB时警告 print(内存不足建议分批处理)这些代码在实际项目中经过验证可以直接集成到你的数据处理流程中。记得根据具体需求调整异常处理逻辑特别是在生产环境中使用时。