转换键值对文本为CSV:避免名称重复并实时累加数值的实现方案
实现方案说明
完全不需要调整现有C程序的输出格式,纯Python标准库即可完成符合要求的CSV转换,核心是先识别采样块的边界,再生成宽表格式的CSV——这种格式本身就是为可视化场景设计的,没有重复列/重复键的问题,直接可以导入Dash、JS图表库使用。
之前实现失败的核心原因
你之前的处理逻辑没有识别「空行分隔的内容属于同一次采样数据」的规则,逐行拆分后直接按两列写入,自然会导致每一行都重复出现相同的键名,最终生成的长表结构完全不适合做时序可视化。
正确的处理逻辑
- 采样块拆分:把整个文本按连续空行切分,每一个切分出来的块就是1秒间隔的单组采样记录
- 逐块解析键值:对每个块里的单行内容,找到第一个连续空白的位置切分前面的键、后面的值,兼容值带冒号、特殊字符的场景(比如
SER#、Checksum字段) - 不重复表头收集:遍历所有块收集出现过的唯一键名作为CSV表头,从根源避免重复列
- 逐行写入:每个采样块对应CSV的一行,按照固定表头顺序填充值,缺失值留空即可
可直接运行的实现代码
import csv # 读取源文件 with open("data.txt", "r", encoding="utf-8") as f: raw_text = f.read() # 按空行拆分独立采样块,过滤空内容 sample_blocks = [blk.strip() for blk in raw_text.split("\n\n") if blk.strip()] parsed_records = [] unique_headers = [] for block in sample_blocks: record = {} for line in block.splitlines(): line = line.strip() if not line: continue # 定位键和值的切分位置:第一个出现连续空白的地方 split_idx = next(pos for pos, char in enumerate(line) if char.isspace()) key = line[:split_idx].strip() value = line[split_idx:].strip() record[key] = value # 收集不重复的表头顺序 if key not in unique_headers: unique_headers.append(key) parsed_records.append(record) # 写入无重复表头的CSV with open("data.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=unique_headers) writer.writeheader() writer.writerows(parsed_records)
适配累加需求的补充逻辑
如果需要对相同名称的数值做累计汇总,可以在所有采样数据写入完成后,针对可转换为数值的字段做全量累加,追加为CSV的最后一行,示例逻辑:
# 跳过非数值类字段的累加 non_numeric_fields = {"PID", "FW", "SER#", "LOAD", "Checksum"} sum_row = {k: "" for k in unique_headers} for field in unique_headers: if field in non_numeric_fields: continue total = 0 for rec in parsed_records: try: total += float(rec.get(field, 0)) except ValueError: continue sum_row[field] = str(total) # 把sum_row追加到CSV末尾即可
生成的CSV效果
最终输出的CSV表头为PID,FW,SER#,V,I,VPP,PPW,CS,ERR,LOAD,H19,H20,H21,H22,H23,HSDS,Checksum,没有重复列,每一行对应一秒的采样数据,可直接被Dash、Chart.js等可视化库读取,无需二次加工。
注:整个解析过程完全兼容你现有C程序的输出格式,不管键和值之间的空格数是2个还是4个,哪怕值中包含冒号、空格等特殊字符,都可以正确解析。
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

