如何使用Python将STDF文件数据转换为Pandas DataFrame
Python读取STDF文件并转换为Pandas DataFrame落地方案
不用找所谓“无缺陷、全文档”的现成STDF处理模块,STDF作为半导体测试设备的通用格式,不同厂商(泰瑞达、爱德万、国产测试机等)都会加自定义私有字段,不存在能100%兼容所有文件的通用模块,自己基于现有稳定解析核心搭轻量流程,适配自己的停机时长分析场景,效率和可控性反而更高。
核心依赖选择
- 解析核心用
pystdf,是目前Python生态下对STDF V4标准规范兼容最稳定的实现,核心记录解析逻辑经过量产场景验证,足够覆盖设备运行时长、停机标记、时间戳这类分析需要的字段,文档不全的问题完全可以通过自定义记录处理器绕开,不需要啃全量源码。 - 数据结构化直接用
pandas+numpy做后续时长计算,不需要额外中间格式转换。
具体实现流程
1. 环境安装
直接安装适配Python3的版本即可,执行命令:
pip install pystdf pandas numpy
2. 流式解析代码(支持大文件,低内存占用)
不要用网上那种全量解析所有STDF字段的写法,几个G的量产STDF文件全量解析很容易内存溢出,自定义收集器只抓和设备运行、停机相关的记录,边读边存,解析速度快很多。
最小可用代码如下:
import pandas as pd import numpy as np from pystdf import V4 from pystdf.IO import Parser class StdfRuntimeDataCollector: def __init__(self): self.records = [] self.current_lot_start_ts = None def send(self, record_type, fields): # 仅捕获和运行时长、停机相关的记录类型,跳过无关测试明细数据 rec_type = record_type.name try: if rec_type == "MIR": # 主信息记录:存批次启动时间戳 self.current_lot_start_ts = fields[V4.MIR.START_T] elif rec_type == "MRR": # 主结果记录:存批次结束时间、异常中断标记 lot_id = fields[V4.MRR.LOT_ID] self.records.append({ "data_type": "lot", "lot_id": lot_id.decode("utf-8") if isinstance(lot_id, bytes) else lot_id, "start_ts": self.current_lot_start_ts, "end_ts": fields[V4.MRR.FINISH_T], "is_abort": fields[V4.MRR.PART_CNT] == 0 }) elif rec_type == "PCR": # 暂停计数记录:存批次内停机的起止时间、原因 pause_rsn = fields[V4.PCR.PAUSE_RSN] self.records.append({ "data_type": "pause", "start_ts": fields[V4.PCR.START_T], "end_ts": fields[V4.PCR.FINISH_T], "pause_reason": pause_rsn.decode("utf-8") if isinstance(pause_rsn, bytes) else pause_rsn }) except: # 碰到厂商自定义字段、格式异常的记录直接跳过,不中断整体解析 pass def to_dataframe(self): df = pd.DataFrame(self.records) # 时间戳统一转datetime格式方便后续计算 for col in ["start_ts", "end_ts"]: df[col] = pd.to_datetime(df[col], unit="s") return df def read_stdf_to_df(file_path: str) -> pd.DataFrame: collector = StdfRuntimeDataCollector() parser = Parser(open(file_path, "rb")) parser.addSink(collector) parser.parse() return collector.to_dataframe()
3. 停机时长计算注意事项
拿到结构化DataFrame后,按两类口径统计停机时长即可,避免统计偏差:
- 批次内停机:筛选
data_type == 'pause'的记录,直接计算end_ts - start_ts的时间差求和,就是批次内暂停、故障、待料的时长,可按pause_reason拆分不同停机原因的占比 - 批次间停机:筛选
data_type == 'lot'的记录按start_ts排序,计算上一个批次end_ts到下一个批次start_ts的差值,就是换批、调机、设备空闲的时长 - 异常停机单独标记:
is_abort == True的批次对应的中断时长,单独归类为故障类停机,和正常待料、换批停机分开统计
适配优化提示
如果碰到部分测试机导出的STDF有特殊时间字段、自定义停机标记,只需要在send方法里加对应记录类型的字段提取逻辑就行,不需要修改底层解析代码,适配单厂商机型的规则通常十几行代码就能搞定,比等通用模块适配效率高很多。
内容的提问来源于stack exchange,提问作者SrinivasaRamanujam N
相关产品推荐
相关产品推荐

