新闻详情

新闻详情

首页 / 资讯中心 / 详情

HTRI二次开发教程(07):输入读写与运行控制——load、change、run、retrieve、save 生命周期

发布时间:2026/9/30 8:48:51来源:尧图网络
HTRI二次开发教程(07):输入读写与运行控制——load、change、run、retrieve、save 生命周期
HTRI二次开发教程07输入读写与运行控制——load、change、run、retrieve、save 生命周期版本与事实声明版本锚点当前Xchanger Suite 9.4官方 Automation Server 演示环境为 Visual Studio 2013 .NET/C#。9.4 增强项含run selected cases individually可单选中案例运行对批量脚本有参考意义。示例代码中的 ProgID、方法名、属性名一律为占位符必须用第 05/06 篇探测所得真实标识符替换后才可运行本系列不写死任何 API 字符串。文中所有数值均为示例性建模不代表任何标准规定不对应任何真实装置。一句话结论HTRI 自动化的骨架就是官方演示的五动作——load打开案例→ change改输入→ run运行→ retrieve取输出→ save保存把它落成可复用脚本的关键不是记住方法名而是三件事模式守卫只写当前模式可写的字段、运行完成判定区分跑完了和跑对了、释放三步超时 try/finally 残留进程清理。〇、本篇要解决的认知问题Q1官方演示的五个动作在真实工程里对应怎样一条生命周期Q2打开案例后为什么当前活动案例是必须显式管理的隐式状态Q3改输入时模式守卫和输出字段只读两条规则怎么落到代码里Q4运行触发了怎么判断它是跑完了还是跑对了Q5为什么释放三步超时、try/finally、清理残留进程是驱动桌面 OLE 的铁律一、机制解析1.1 官方五动作 → 工程生命周期官方 TechTip 明确列出 Automation Server 能做的五件事loading an existing case、changing input data in a case、running a case、retrieving output data from a case、saving a case。映射到工程[准备] 许可/环境检查 → 定位模板案例 ↓ [load] 打开案例副本 ↓ [change] 按模式守卫写入输入字段 ↓ [run] 触发行计算 → 判定完成与收敛 ↓ [retrieve] 读取输出字段仅在完成后 ↓ [save] 另存为派生案例绝不覆盖模板 ↓ [释放] 断开连接 → 清残留进程为什么这对你重要这七步就是后续所有脚本第 08/09/10/16/17 篇的公共骨架。把骨架写对一次参数扫描、批量校核、平台化都只是在这个骨架上换改什么、扫什么。1.2 显式会话拒绝当前活动案例官方 Features 页称软件可同时打开多个案例文件。这在批处理里是陷阱如果你的代码依赖当前活动案例这种隐式状态一旦有并行会话或异常恢复你极可能把 A 案例的输入写到 B 案例、把 B 的输出记到 A 名下。最佳实践一个案例一个显式句柄。用变量持有案例对象所有读写都通过它进行禁止任何再取一次当前案例的操作。异常恢复时凭句柄判断我操作的是谁。1.3 模式守卫与输出字段只读第 04 篇的Node.writable[mode]与输出字段所有模式皆不可写两条规则在 change 阶段必须强制执行写之前查writable[mode]为假则跳过并记录而不是抛异常中断整批输出字段如out.summary.overall_u永不在 change 阶段出现遇到留空由能量平衡补算的量显式声明本次给还是不给。反直觉点跳过不等于忽略。跳过要记账——每批任务结束后统计哪些字段因模式不匹配被跳过这是发现我是不是理解错了模式的重要信号。1.4 运行完成判定跑完了 ≠ 跑对了触发行计算只是发起。判定运行结果要分两层完成判定进程/计算是否结束超时是重要信号质量判定是否有警告warning、是否收敛、结果是否物理合理。官方 Xist 提供振动 screening 警告、局部/整体结果报表等质量判定这些信号在哪、叫什么依赖本机探测U2。工程上至少要做到默认不信任返回了就算成功而是去读警告/状态类输出字段或报表。1.5 释放三步铁律 6桌面 OLE 自动化最典型的故障是挂死与残留进程。因此铁律 6任何驱动桌面 OLE 的代码必须含超时给整个会话设上限如总时长 单次运行上限try/finally释放无论成功失败都执行断开连接残留进程清理任务结束后清点进程清理没退干净的实例。这三步不是锦上添花而是批量任务能否无人值守的分水岭。1.6 为什么五步的顺序不能变为什么这对你重要生命周期里最贵的错误往往不是某一步写错了而是顺序错了——因为顺序错误通常不报错只给你一个看起来正常的错结果。四条顺序铁律load 必须在 change 之前没有案例句柄你改的是空气change 必须在 run 之前run 是对当前输入的求解改完才跑retrieve 必须在 run 完成之后这是第 09 篇纪律一的根源——早取数拿到的是上一轮save 必须用新路径覆盖模板会让后续所有派生案例错乱第 08 篇模板只读的根源。一条反直觉结论顺序比正确性更难保证。语法错误会立刻报错顺序错误会静默传播——你会在几天后发现整批结果都偏移了却找不到是哪一步错了。所以生命周期骨架应该写死成函数、只允许按序调用而不是散在业务代码里靠自觉。这正是代码 7-1 把它封装成sessionrun_one的原因。二、完整代码与逐行剖析代码 7-1完整生命周期脚本占位符 释放三步# -*- coding: utf-8 -*- drive_case.py —— 单案例 OLE 生命周期load→change→run→retrieve→save 用法python drive_case.py template.htri output_case.htri 【重要】所有 ... 标识符必须换成第 05/06 篇探测所得真实值。 工程护栏模式守卫 完成判定 释放三步铁律 6。 importsysimporttimeimportjsonimportsubprocessimportwin32com.clientaswcfromcontextlibimportcontextmanager PROGIDHTRIAutomationServer.ProgID本机枚举所得OP_LOAD打开案例的方法探测所得OP_RUN运行案例的方法探测所得OP_SAVE另存案例的方法探测所得SESSION_TIMEOUT_S600# 整个会话上限秒RUN_TIMEOUT_S300# 单次运行上限秒defload_writable_map(pathdatadict.csv):从数据字典读入 规范路径 - (real_identifier, writable[mode])。importcsv out{}forrincsv.DictReader(open(path,encodingutf-8-sig)):identr.get(real_identifier,).strip()ifnotident:continue# 未探测确认的字段一律不进映射out[f{r[group]}.{r[field]}]{ident:ident,w:{rating:r[writable_rating]True,simulation:r[writable_simulation]True,design:r[writable_design]True,},}returnoutdefset_field(case,node_path,value,mode,wmap,skipped):按模式守卫写入一个字段不可写则记录并跳过。entrywmap.get(node_path)ifentryisNone:skipped.append((node_path,未在数据字典登记))returnifnotentry[w].get(mode,False):skipped.append((node_path,f模式{mode}下不可写))returnnodecaseforpartinentry[ident].split(.):# 逐层下降真实标识符路径nodegetattr(node,part)setattr(node,叶子属性名探测所得,value)contextmanagerdefsession(progid,timeout_s):会话上下文负责创建、超时守护与 finally 释放。ifprogid.startswith():raiseRuntimeError(PROGID 仍是占位符请先完成探测)appwc.gencache.EnsureDispatch(progid)starttime.time()try:yieldapp,startfinally:# 释放无论成功失败都尝试断开try:appNone# 释放引用触发 COM 释放exceptException:# noqa: BLE001passdefcleanup_leftover():清点可能的残留进程只做只读清点是否结束由用户决定。try:outsubprocess.run([tasklist,/FO,CSV,/NH],capture_outputTrue,textTrue,timeout30)lines[lforlinout.stdout.splitlines()ifhtriinl.lower()orxchangerinl.lower()]iflines:print(f[警告] 检测到{len(lines)}个疑似残留进程关键字 htri/xchanger)forlinlines[:10]:print( l)print( 请人工确认后处理不要在未确认时批量结束进程。)else:print([OK] 未发现明显残留进程。)exceptExceptionase:# noqa: BLE001print(f[提示] 进程清点跳过{e})defmain():iflen(sys.argv)3:print(用法python drive_case.py template.htri output_case.htri)returntemplate,out_casesys.argv[1],sys.argv[2]moderating# 本次运行意图示例wmapload_writable_map()skipped[]withsession(PROGID,SESSION_TIMEOUT_S)as(app,start):casegetattr(app,OP_LOAD)(template)# load用副本# change示例写入值均为示例性建模set_field(case,geometry.exchanger.shell_id,800.0,mode,wmap,skipped)set_field(case,process.duty,1500.0,mode,wmap,skipped)# run发起并等待真实 API 形式以探测为准getattr(case,OP_RUN)()iftime.time()-startRUN_TIMEOUT_S:raiseTimeoutError(运行超时)# retrieve完成后再取示例从输出分组逐字段读取results{}fornorm_path,entryinwmap.items():ifnotnorm_path.startswith(outputs.):continue# 只取输出分组nodecaseforpartinentry[ident].split(.):nodegetattr(node,part)results[norm_path]getattr(node,叶子属性名探测所得)print(f[retrieve] 取到{len(results)}个输出字段)getattr(case,OP_SAVE)(out_case)# save另存不覆盖模板cleanup_leftover()ifskipped:print([跳过字段])forpath,whyinskipped:print(f -{path}:{why})if__name____main__:main()说明为控制篇幅代码中retrieve段用了一个占位骨架——真实取数应逐字段读取输出节点第 09 篇给出完整实现此处只强调取数必须发生在 run 完成之后。逐行剖析load_writable_map只收real_identifier非空的条目未经探测确认的字段不进映射从机制上杜绝用猜的标识符编码。set_field的两级守卫先查数据字典是否登记、再查模式是否可写不可写就skipped.append并静默跳过——批量任务里跳过并记账比抛异常中断整批友好得多。session用contextmanager把创建 超时起点 finally 释放封装起来这是铁律 6 前两步的落地app None释放引用是 pywin32 释放 COM 对象的常用手法。cleanup_leftover只做只读清点并提示人工确认脚本不擅自结束进程——误杀他人会话是安全事故工程纪律要求只报警不越权。OP_LOAD/OP_RUN/OP_SAVE与叶子属性名都是占位符官方演示告诉我们有这五个动作但具体方法名要探测U2。out_case与template分离绝不覆盖模板——模板是批处理的基准一旦被改写后续全部派生案例都会错。代码 7-2超时守护装饰器独立可运行# -*- coding: utf-8 -*- with_timeout.py —— 给任意阻塞型调用加超时Windows 采用线程 兜底标记 说明OLE 调用是阻塞的Python 无法直接强杀线程本脚本提供 软超时——到点后抛出 TimeoutError 让上层释放会话并清理进程。 importthreadingimportfunctoolsimporttimedefsoft_timeout(seconds):defdeco(fn):functools.wraps(fn)defwrapper(*args,**kwargs):result{}deftarget():try:result[ok]fn(*args,**kwargs)exceptExceptionase:# noqa: BLE001result[err]e tthreading.Thread(targettarget,daemonTrue)t.start()t.join(seconds)ift.is_alive():# 无法强杀线程交由上层释放 COM 清理进程raiseTimeoutError(f{fn.__name__}超过{seconds}s 未返回)iferrinresult:raiseresult[err]returnresult.get(ok)returnwrapperreturndecosoft_timeout(2)defdemo_blocking():time.sleep(5)returndoneif__name____main__:print(演示2 秒超时对 5 秒阻塞函数的判定)try:demo_blocking()print(未超时不应出现)exceptTimeoutErrorase:print(已按预期超时,e)逐行剖析必须承认的机制限制Python 不能强行终止一个正在阻塞的线程。所以这里是软超时——到点就抛错把清理交给上层。诚实标注限制比假装能强杀更工程。daemonTrue让超时后的守护线程不阻止主程序退出但线程仍在跑因此上层必须做进程清理cleanup_leftover。异常经result[err]回传再重抛把子线程异常带回主线程避免子线程报错、主线程以为没事。独立可运行这段代码零外部依赖任何机器都能跑通验证超时判定逻辑本身是否工作。三、常见报错与排查报错 3-1任务跑完后进程还在越跑越多。现象批量循环后tasklist里 HTRI 实例堆积。根因没有在finally里释放 COM 引用或异常路径跳过了释放。解法用session上下文管理器代码 7-1保证 finally 必执行任务后跑cleanup_leftover清点。报错 3-2com_error: 服务器运行失败 (RPC_E_SERVERFAULT)或调用挂死。现象某次run长时间不返回。根因桌面 OLE 调用的典型阻塞也可能是案例本身算不动或弹了对话框。解法加软超时代码 7-2超时后释放会话并清理进程注意桌面交互弹窗会阻塞无人值守批处理机应避免需要人工确认的弹窗以本机行为为准。报错 3-3脚本覆盖了模板案例后续全部派生案例错乱。现象模板被改写扫描结果整体偏移。根因save写到了模板路径。解法强制load 模板 save 到全新路径可在脚本里断言out_case ! template。报错 3-4写入字段无异常但结果不变。现象set_field不报错结果没动。根因模式不可写已被守卫跳过或写入的是只读节点。解法查看skipped输出对照datadict.csv的 writable 三列若确应可写用第 06 篇测绘复核real_identifier是否指向了正确叶子。报错 3-5取输出取到的是上一轮的结果。现象本轮改了输入读出的结果与上轮相同。根因在 run 完成前就取数或复用了上轮会话。解法取数严格排在 run 完成后每轮用独立会话/独立案例句柄禁止跨轮复用。四、动手练习练习 1骨架跑通用探测所得真实标识符替换代码 7-1 的占位符对一个副本案例跑通 load→change→run→retrieve→save。判定生成派生案例文件模板文件修改时间不变。练习 2模式守卫故意在同一案例上以 rating 模式写入一个仅 simulation 可写的字段。判定脚本不报错中断skipped中出现该字段及原因模式 rating 下不可写。练习 3超时演练运行代码 7-2。判定控制台打印已按预期超时且在 2 秒左右返回不是 5 秒。练习 4释放三步复核在一次完整运行后执行cleanup_leftover。判定输出为[OK] 未发现明显残留进程若报检测到残留能解释是哪一步没释放并修复。五、小结与下一篇预告本篇把官方五动作落成了一条带工程护栏的生命周期load 用副本、change 带模式守卫并记账、run 判定完成与质量、retrieve 严格在完成后、save 另存不覆盖并用try/finally 软超时 残留进程清点实现释放三步铁律 6。骨架对了后面所有批量场景都是换变量、换目标。第 08 篇《实战一Xist 参数扫描》我们把这条骨架套进一个真实的批量场景——对管壳式换热器做全因子/拉丁超立方参数扫描配上变量-目标契约、批量状态机提交→运行→超时→重试与断点账本并对照官方 Parametric Study Tool 说明何时用官方工具、何时自己写。本篇认知问题回显FAQQ1官方五动作在工程里对应怎样一条生命周期Aload打开案例→ change按模式守卫改输入→ run触发行计算并判定完成/收敛→ retrieve仅在完成后取输出→ save另存为派生案例绝不覆盖模板前后各加准备许可/路径检查“与释放断开连接 清残留进程”。这套七步骨架是第 08/09/10/16/17 篇共用的公共结构。Q2为什么当前活动案例必须显式管理A官方称软件可同时打开多个案例文件若代码依赖当前活动案例这种隐式状态一旦有并行会话或异常恢复就可能把 A 的输入写到 B、把 B 的输出记到 A。最佳实践是一个案例一个显式句柄所有读写都经该句柄进行禁止再取一次当前案例。Q3模式守卫与输出字段只读怎么落代码A写字段前先查数据字典的writable[mode]为假则跳过并记入skipped清单静默跳过并记账而非抛异常中断整批输出字段如out.summary.overall_u永不出现在 change 阶段。set_field还强制要求该字段已在数据字典登记且real_identifier非空从机制上杜绝用猜的标识符编码。Q4怎么判断运行是跑完了还是跑对了A分两层判定。完成判定看计算是否结束超时是关键信号质量判定要看是否有警告、是否收敛、结果是否物理合理Xist 有振动 screening 警告与各类结果报表具体字段以本机探测为准。默认不信任有返回即成功而应显式读取状态/警告类输出。Q5为什么释放三步是驱动桌面 OLE 的铁律A桌面 OLE 调用最典型的故障是挂死与残留进程堆积。三步为给会话与单次运行设超时Python 无法强杀阻塞线程故为软超时到点抛错交由上层清理用try/finally代码中用 session 上下文管理器保证任何路径都释放 COM 引用任务后清点残留进程。脚本只做只读清点并提示人工确认不擅自结束进程。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

OpenCSG Agentic-27B 正式开源:27B Dense 模型,Agent 执行能力实现全面跃升 2026/9/30 9:36:25

OpenCSG Agentic-27B 正式开源:27B Dense 模型,Agent 执行能力实现全面跃升

当大模型接入邮件、日历、知识库、CRM、库存和工单系统,评价模型的标准也随之改变。 在真实工作流中,模型需要理解系统约束,选择合适的 Skill 和工具,生成合法参数,读取工具返回值,处理失败分支&#xff0…

阅读更多 →
Qwen-Image-2.1本地部署实战:--lowvram、GGUF量化与多模型对比 2026/9/30 9:36:18

Qwen-Image-2.1本地部署实战:--lowvram、GGUF量化与多模型对比

Qwen-Image-2.1 发布后,我在本地前前后后跑了三轮测试。第一轮是最朴素的"默认参数直接跑",结果在 4090 上都给我弹了 CUDA out of memory;第二轮改成 fp8 加各种 offload,总算能出图,但速度和稳定性还是怪怪的;到了第三轮,也就是这次,我把--lowvram这个参数单独拎出…

阅读更多 →
基于LSTM的PM2.5浓度预测:数据清洗到模型训练全流程 2026/9/30 9:36:18

基于LSTM的PM2.5浓度预测:数据清洗到模型训练全流程

简介:基于LSTM循环神经网络的PM2.5预测PDF,是一份聚焦空气质量预测的学术论文,面向环境科学、数据建模与机器学习方向的研究者和学生。针对PM2.5浓度变化突发、非线性且传统方法难以准确预测的问题,该研究将气象与大气污染物指标作…

阅读更多 →
机器人视觉项目实战:从进场勘察到验收交付的避坑指南 2026/9/30 9:36:17

机器人视觉项目实战:从进场勘察到验收交付的避坑指南

搞了这么多年机器人视觉项目,从前期技术交流到进场安装调试,再到最终验收交付,我发现自己真正长记性的地方,不是在办公室里对着PPT做方案的时候,而是在客户现场被现实狠狠教育的那几次。最近整理手头的项目笔记&#x…

阅读更多 →
Codex 接入 Jev 实战:TypeSafe 配置与 Skill 扩展解决 API Key 报错 2026/9/30 9:36:11

Codex 接入 Jev 实战:TypeSafe 配置与 Skill 扩展解决 API Key 报错

1. 从一条报错说起:为什么我要折腾 Codex 配 Jev 先说结论:Codex 本身是个很好用的编码代理工具,但它的默认模型链路和 API Key 管理方式,在国内网络环境下经常让人抓狂。我最初用 Codex 的时候,遇到最多的就是 unexp…

阅读更多 →
智能体落地实操指南:框架选型、Prompt工程与状态管理 2026/9/30 9:36:11

智能体落地实操指南:框架选型、Prompt工程与状态管理

1. 这不是“又一篇综述”,而是一份智能体落地实操手记最近在几个高校实验室和产业项目组里,反复被问到一个问题:“智能体(Agent)到底是不是炒作?我们团队想上手,该从哪切入?论文里那…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉