EP03 · 讲义
Genesis2000 Python 脚本实战 · 第3集 MainInfo——info 查询
本集学什么
这集讲查询。学完你能独立写出查询代码:查料号清单、查步骤、查层别、查矩阵,都用一行调用完成。 方法按实体层级组织,和 Genesis 的模型一一对应。我们先看两条查询通道,再逐层往上。
回顾:第 2 集的通信底图
- 第 2 集:GFDO_INFO 通道 = 临时文件 + 解析器
tmp_list['gJOBS_LIST']
上一集讲过,查询走临时文件通道:发 info 命令把结果写进临时文件,读回、解析成字典。 MainInfo 的全部查询方法,就建立在这条通道上。它只做两件事:拼好查询参数,取出需要的键。
定位:四层的第二层
class MainInfo(IncamClasses.InCAM)
- 1319 行
- 职责只有两个字:查询
- 料号 / 步骤 / 层别 / 矩阵 / 铜箔面次
MainInfo 直接继承上一集讲的 InCAM 类,所以通信、解析这些能力它全都有。 它的职责只有两个字:查询。料号列表、步骤列表、层别信息、矩阵信息、铜箔面次——凡是「想知道什么」,找 MainInfo。
两条查询通道
通道一 GFDO_INFO → 临时文件 → 解析成字典
通道二 COM 写文件 → 自行读原始行
查询走两条通道。第一条是 GFDO_INFO:结果写临时文件,解析成字典再返回——适合规整的键值数据。 第二条是直接发 info 命令、指定输出文件,自己读原始行——适合需要原始文本的场景,比如轮廓报告。
JobList:最简解剖(完整源码)
def JobList(self):
tmp_list = self.do.GFDO_INFO("-t root -d JOBS_LIST") sublist = tmp_list['gJOBS_LIST']
return sublist
先解剖最简单的方法:查料号列表。总共两行——第一行发查询,参数指定根实体和数据类型;第二行从返回字典取出需要的键。 所有复杂机制——通信、临时文件、解析——都在底层。MainInfo 的方法只表达「查什么、取什么」。
info 命令的参数语法
info,args=-t root -d JOBS_LIST,out_file=<文件>,write_mode=replace,units=inch
那条查询串值得展开。info 命令参数有自己的语法:t 指定实体类型,d 指定数据项,e 指定具体实体名,m 指定模式。 外层还有三个通用参数:out_file 输出到哪个文件,write_mode 覆盖还是追加,units 用什么单位。这套语法来自官方文档,MainInfo 只是帮你把参数拼好。
实体层级查询族
- JobList 料号
- StepList(job) 步骤
- LayerList(job,step) 层别
- LayerType(job,step,layer) 层类型
- job → step → layer 逐层深入
- 与官方寻址体系完全一致
查询方法按实体层级组织,正好对应 Genesis 的实体模型:料号、步骤、层别逐层深入。 参数一路往下传:job、step、layer。这和官方文档的寻址体系完全一致——学一次,处处通用。
不存在就返回 noexists
return "noexists" # 哨兵值,不抛异常
- 调用方优雅判断,不用到处 try/except
- 全包通用约定
有个约定值得单独讲:查询的实体不存在时,MainInfo 返回哨兵值 noexists,而不是抛异常。 好处是调用方写起来简单:拿到结果先判一下是不是 noexists,是就走另一条分支,不需要到处包 try except。这个约定全包通用。
StepProf:走文件的实例(完整源码)
COM info,out_file=<job.prof>,units=inch,args=-t step -e job/step -m script -d PROF
lines = 读文件
del lines[0] # 去掉表头行
return [i[1:] for i in lines] # 跳过每行第一个字符
再看走文件的实例:查轮廓报告。直接发 info 命令把结果写进指定文件,读回所有行。 细节很有意思:先删掉第一行——那是表头不是数据;再用切片跳过每行第一个字符。这些「脏活」正是封装的价值:调用方拿到的直接是干净数据。
单位参数的模式
units = 'inch' # 默认值
for key in args: # 遍历参数字典
if key == 'units': units = ... # 命中即覆盖
MainInfo 处理可选参数有固定模式:先设默认值,再遍历参数字典,命中哪个键就覆盖哪个。 单位默认英寸,调用方传 units 就切换。写法朴素,但读起来一眼明白——这也是整个包的老风格。
矩阵查询:一次取回多组平行数据
matrix = GFDO_INFO("-t matrix -e job/matrix")- 行名 / 行序 / 面次 / 类型 / 极性 各是一列
- 第几个元素对应同一层
现在看全包最复杂的查询:矩阵信息。一条命令查回来的不是单值,而是多个平行数组——行名、行序、面次、类型、极性,各是一列。 所谓平行,就是每个数组的第几个元素对应同一层。接下来要做的,是按索引把这一排排数据拆开、重新组织。
按索引拆层:核心循环
for i in range(...): # 按索引逐层拆
层名 = 行名[i]; 面次 = 面次[i] ...
以层名为键装进字典
拆法的核心是一个循环:按索引把每一层的行名、行序、面次逐个取出来,以层名为键重新装进字典。 这样「矩阵」这个二维表格,就变成了「以层为单位」的一维字典——上层要哪层的哪项属性,直接取。
中文类别:正则归类
拆开之后,方法用几十条正则把每层归入中文类别:名称匹配防焊的归防焊层别,匹配钻孔的归钻孔层别,激光钻孔、文字、外层各有各类。 最后产出一个全中文的字典:所有层别排好序,每层的面次、类型、极性各就各位。不懂英文术语的同事也能直接读——这就是业务价值。
中文键的惯例
LayerStrEnd → {'开始层': ..., '结束层': ...}中文键不止矩阵一个例子。查层的起止位置,返回的字典键就是「开始层」「结束层」。 这形成了一条设计惯例:底层保留原始键名,面向用户的聚合结果用中文键。读代码时看到中文键,就知道这是给业务层用的接口。
JobPath:平台分支(完整源码)
if INCAM_PRODUCT 存在:
COM get_job_path → 取 COMANS
else:
dbutil 二进制 → 取返回行
再看一个有意思的方法:查料号路径。InCAM 环境和 Genesis 环境的实现不一样——一个走命令,一个走外部程序。 方法内部用环境变量判断平台,自动选实现,调用方完全不感知差异——这就是封装给跨平台脚本的甜头。
硬编码路径的工程故事
- OpenJobList 写死 /genesis/tmp/
- 注释:自动任务时无法获取环境变量,改为绝对路径
- 和第 2 集 edir 注释同一个故事
- 写路径前先想清楚运行场景
最后看一处工程故事。有个方法读作业列表时,路径写死成了绝对路径,旁边注释写着原因:自动任务时无法获取环境变量。 和第 2 集 edir 的注释是同一个故事:自动化场景下环境变量靠不住。看到这类注释,就是在提醒你:写路径前先想清楚它运行的场景。
使用案例巡览
joblist = Do.JobList() # 获取料号清单
Do.do.ask_matrix_info('job') # 矩阵中文归类Do.LayerList('job', 'step') # 层别清单- 摘自包内 docstring「使用例子」原文
- 第 6 集业务模块大量调用它们
最后看真实用法,三个例子都摘自包内文档。查料号清单一行;查矩阵信息一行,拿到的直接是中文类别字典;查层别清单也是一行。 第 6 集的业务模块,就是大量调用这些查询接口组装出更复杂的能力。地基打好了,楼上才好盖。
小结与预告
回顾这集。MainInfo 的心法有三条:方法名和参数就是文档;用哨兵值代替异常;面向用户的返回用中文键。 查询讲完了,但自动化不能只查不动。下一集看四层中最大的 MainLCM——约一百二十个操作命令是怎么封装的。
零壹AI工作室出品 · 《用 Python 驱动 Genesis2000》免费公开课 · www.binwindai.com