EP03 · 讲义

Genesis2000 Python 脚本实战 · 第3集 MainInfo——info 查询

本集学什么

这集讲查询。学完你能独立写出查询代码:查料号清单、查步骤、查层别、查矩阵,都用一行调用完成。 方法按实体层级组织,和 Genesis 的模型一一对应。我们先看两条查询通道,再逐层往上。

回顾:第 2 集的通信底图

tmp_list['gJOBS_LIST']
上一集讲过,查询走临时文件通道:发 info 命令把结果写进临时文件,读回、解析成字典。 MainInfo 的全部查询方法,就建立在这条通道上。它只做两件事:拼好查询参数,取出需要的键。

定位:四层的第二层

class MainInfo(IncamClasses.InCAM)
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 只是帮你把参数拼好。

实体层级查询族

查询方法按实体层级组织,正好对应 Genesis 的实体模型:料号、步骤、层别逐层深入。 参数一路往下传:job、step、layer。这和官方文档的寻址体系完全一致——学一次,处处通用。

不存在就返回 noexists

return "noexists"   # 哨兵值,不抛异常
有个约定值得单独讲:查询的实体不存在时,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 环境的实现不一样——一个走命令,一个走外部程序。 方法内部用环境变量判断平台,自动选实现,调用方完全不感知差异——这就是封装给跨平台脚本的甜头。

硬编码路径的工程故事

最后看一处工程故事。有个方法读作业列表时,路径写死成了绝对路径,旁边注释写着原因:自动任务时无法获取环境变量。 和第 2 集 edir 的注释是同一个故事:自动化场景下环境变量靠不住。看到这类注释,就是在提醒你:写路径前先想清楚它运行的场景。

使用案例巡览

joblist = Do.JobList()              # 获取料号清单
Do.do.ask_matrix_info('job')        # 矩阵中文归类
Do.LayerList('job', 'step')        # 层别清单
最后看真实用法,三个例子都摘自包内文档。查料号清单一行;查矩阵信息一行,拿到的直接是中文类别字典;查层别清单也是一行。 第 6 集的业务模块,就是大量调用这些查询接口组装出更复杂的能力。地基打好了,楼上才好盖。

小结与预告

回顾这集。MainInfo 的心法有三条:方法名和参数就是文档;用哨兵值代替异常;面向用户的返回用中文键。 查询讲完了,但自动化不能只查不动。下一集看四层中最大的 MainLCM——约一百二十个操作命令是怎么封装的。
零壹AI工作室出品 · 《用 Python 驱动 Genesis2000》免费公开课 · www.binwindai.com