# P2-00 端到端冒烟与 NX Open API 实测发现

> 执行者：验收方（DeepSeek Harness）　时间：2026-10-16 17:49–17:56
> 目的：验证"外部程序 → 指定版本 NX 批处理 → NX Open API 操作真实模型 → 回收结果"这条链路
> 方式：用 P0-03 的 `nx_launch.ps1` 真实启动两版 NX，执行探针 journal 打开真实零件
> 证据：`D:\NX_AI\状态\part_probe_result.txt`、`part_probe_diag.txt`、`C:\NX_AI\日志\run_journal_*.log`

## 1. 链路验证结果：两个版本都通

| 项目 | NX2212 | NX2412 |
|---|---|---|
| `nx_launch.ps1 -Mode journal` 真实执行 | ✅ 成功 13–15 秒 | ✅ 成功 15 秒 |
| 子进程退出码 | 0 | 0 |
| 内嵌 Python | 3.10.6 | 3.11.9 |
| `import NXOpen` + `Session.GetSession()` | ✅ | ✅ |
| `Parts.OpenActiveDisplay(真实零件)` | ✅ 打开成功 | ✅ 打开成功 |
| `part.Leaf` | 后盖铝板-LQD80-镜像-175电机 | 同 |
| `-AssertNoGlobalChange` 自检 | ✅ 通过 | ✅ 通过 |

**结论：路线 A（外部程序 + run_journal 驱动脚本）在真实零件上成立**，
`nx_launch.ps1` 的进程级环境构造与版本切换经真机验证有效，全局环境变量 4 次运行零改动。

## 2. NX Open API 实测行为矩阵（重要：直接照抄会踩坑）

| API 写法 | NX2212 | NX2412 | 结论 |
|---|---|---|---|
| `len(part.Bodies)` | ❌ TypeError: no `__len__` | ❌ 同 | **不能用** |
| `part.Bodies.GetLength()` | ❌ AttributeError | ❌ 同 | 不存在 |
| `part.Bodies.ToArray()` | ❌ AttributeError | ❌ 同 | 不存在 |
| `list(part.Bodies)` | ✅ 92 | ✅ 2 | **唯一可移植方式** |
| `sum(1 for _ in part.Bodies)` | ✅ 92 | ✅ 2 | 同上 |
| `len(part.Features)` | ❌ TypeError | ❌ 同 | 不能用 |
| `part.Units` | 返回**类对象** `NXOpen.PartUnits` | 同 | 访问器不对，取不到值 |
| `part.Units == NXOpen.PartUnits.Millimeters` | ❌ False | ❌ False | 恒 False，不可用 |

## 3. 两个未解释的问题（已开卡要求查清）

1. **实体数 92 vs 2**：同一个零件、同一种迭代方式，两个版本结果差 46 倍。
   这不是笔误。任何"按 NX 对象计数"的业务逻辑（BOM、电极数量、批量导出条目、工序统计）
   都会因此出错。**必须查清**（假设方向：NX2412 是否只加载了部分实体、是否进入轻量化/只读模式、
   是否需显式加载组件）。
2. **`part.Units` 访问器**：在 NX Open Python 绑定里返回的是类型而非值。需要找到正确路径
   （可能是 `part.PartUnits`），或改用别的方式判定单位制。

## 4. 对任务书与后续开发的影响

- **所有 NX 侧脚本必须用迭代取值，禁止 `len()`/`ToArray()`** → 已开 P2-05 建兼容层
- **任何跨版本使用的 API 都必须逐版本实测**，不能假设一致 → 兼容矩阵必须随版本扩充
- `nx_launch.ps1` 的 `-AssertNoGlobalChange` 是有效护栏，应保留为所有启动路径的默认开关
- 运行很快（13–18 秒/次），许可占用时间短，适合作为批量任务的执行后端