NXOpen Python API二次开发环境配置

NXOpen Python API二次开发环境配置

NXOpen Python API二次开发环境配置

前言

最近在工作中遇到一些NX二次开发的工作,有一些深度学习与NX交互的工作内容,尝试使用使用python进行二次开发。在网上搜了几个环境配置的教程,都没有实现代码提示的功能,最近找到生成.pyi文件的方法才实现了代码提示功能,把完整的配置流程给大家分享。

1 安装NX和对应版本的python

1)在NX安装目录下D:\安装目录\NX1946\NXBIN\python找到python37.dll文件,查看文件属性。如安装的是 NX1946,可以查看到对应的python版本是3.7.5。

在这里插入图片描述

2)下载对应的python版本安装到将要用于项目开发的文件夹中,直接使用安装环境,避免虚拟环境的各种问题。如直接安装在D:\NXOpenPython中。

2 添加nxopen库

1)在D:\NXOpenPython\python37\Lib\site-packages目录中新建一个nxopen.pth的文件在文件中添加D:\安装目录\NX1946\NXBIN\python。

2)添加UGII目录到系统变量PATH下。

PATH = D:\安装目录\NX1946\UGII; D:\安装目录\NX1946\NXBIN\

3)进入IDLE进行测试。

在这里插入图片描述


在这里插入图片描述

3 在Pycharm中新建项目

1)python解释器使用刚安装的python,并添加NXBIN目录。

在这里插入图片描述


在这里插入图片描述

已经能调到NXOpen的API了,但是只能提示到安装包,没有函数提示功能。

在这里插入图片描述

4 IED中实现代码提示功能

PyCharm 本身并不直接“解析” .pyd 文件(Windows 下的 Python 扩展模块,本质上是 DLL 文件),因为 .pyd 是编译后的二进制文件,不是源代码。但如果你希望在 PyCharm 中获得代码补全、类型提示、跳转定义等 IDE 功能支持,那么你需要采取一些额外措施,因为 PyCharm 无法从 .pyd 文件中读取函数签名或文档。

为了让 PyCharm 提供智能提示(自动补全、参数提示、跳转等),你需要提供 类型存根(stub files),即 .pyi 文件。(在方头狮https://www.cnblogs.com/unm001/p/16259771.html?_refluxos=a10找打了生成.pyi的代码)

  • 先运行这个代码,生成 NXOpen 文件夹,
  • 再把这个文件夹移动到 NXBIN/python目录下。
 __version__ ="0.0.4" __author__ ="unmht"from typing import Dict, Generator, List, Optional import NXOpen import types import os import re from importlib import import_module ugii_base_dir = os.getenv("UGII_BASE_DIR") pp = os.path.join(str(ugii_base_dir),"nxbin","python") imp_mds ={}for root, dirs, files in os.walk(pp, topdown=True):if root != pp:breakfor ff in files:# print(ff)ifstr(ff).startswith("NXOpen_")andstr(ff).endswith(".pyd"): module_name =str(ff)[:-4]# print(module_name)try: ms = module_name.split("_")[-1] imp_mds[ms]= import_module(module_name)except Exception as e:print("error:", module_name, e)classpyibase: ecpts =["NXObject","TaggedObject","INXObject",]def__init__(self)->None: self.name:str="" self.doc: Optional[str]="" self.chdmdls: Dict ={} self.chdtps: Dict ={} self.MdDescriptor: Dict ={} self.GSDescriptor: Dict ={} self.unct: Dict ={} self.nxc: Dict[str,"nxoClsAliasType | pyibase"]={} self.mthdorbutin: Dict ={} self.mberDescriptor: Dict ={} self.tpsinvoke: Dict[str, List]={} self.nn: List[str]=[]defdcts(self)-> Generator["pyibase",None,None]:for dc in[ self.chdmdls, self.chdtps, self.MdDescriptor, self.GSDescriptor, self.unct, self.nxc, self.mthdorbutin, self.mberDescriptor,]:for v in dc.values():yield v defaddmember(self, m, dm: List[str]=None): dirm =dir(m)if dm isnotNone: dirm =[i for i in dirm if i notin dm]for i in dirm:if i =="GetSession":print(i)ifnot i.startswith("_"): att =getattr(m, i) self.nn.append(i)ifisinstance(att, types.ModuleType): self.chdmdls[i]= nxoModuleType(att)elifisinstance(att,type):if i != att.__name__: self.tpsinvoke[i]=[att.__module__, att.__name__]elif i notin pyibase.ecpts: self.chdtps[i]= nxoType(att)elifisinstance(att, types.MethodDescriptorType): self.MdDescriptor[i]= nxoMethodDescriptorType(att)elifisinstance(att, types.GetSetDescriptorType): self.GSDescriptor[i]= nxoGetSetDescriptorType(att)elifisinstance(att, types.MemberDescriptorType): self.mberDescriptor[i]= nxoMemberDescriptorType(att)else: _md = att.__class__.__module__ if"NXOpen"instr(_md): self.nxc[i]= nxoClsAliasType(att, i)elif i =="ValueOf": self.mthdorbutin[i]= nxoBuiltinFunctionType(att)elifisinstance(att, types.BuiltinFunctionType): self.mthdorbutin[i]= nxoBuiltinFunctionType( att, cname=self.name )else:assert TypeError(i, att,type(att))defdocs(self, lv:int=0, mx:int=130): dd =str(self.doc) dd = dd.strip() dd2 = dd.splitlines() dd2 =[i.strip()for i in dd2] ll = mx - lv *4yield(lv +1)*"\t"+"'''"yield(lv +1)*"\t"+f"### {self.__class__.__name__}"for i in dd2:for k inrange(0,len(i), ll):yield(lv +1)*"\t"+ i[k :min(len(i), k + ll)]yield(lv +1)*"\t"+"'''"deftoStr(self, lv:int=0, mx:int=130):yield lv *"\t"+f"{self.name}:-->"classnxoModuleType(pyibase):def__init__(self, m: types.ModuleType)->None:super().__init__()assertisinstance(m, types.ModuleType) self.doc = m.__doc__ self.name = m.__name__.split(".")[-1] self.addmember(m)deftoStr(self, lv:int=0, mx:int=130):yield lv *"\t"+f"class {self.name}:"for i in self.docs(lv):yield i for dc in self.dcts():for i in dc.toStr(lv +1):yield i for i, v in self.tpsinvoke.items(): _a =".".join(v)yield"\t"+f"{i}={_a}"classbasetps(pyibase):def__init__(self, m:type, name="")->None:super().__init__()assert name in pyibase.ecpts self.name = name self.doc = m.__doc__ self.mo =type.mro(m) self.addmember(m)deftoStr(self, lv=0, mx=130):if self.name in["TaggedObject","INXObject"]:yield lv *"\t"+f"class {self.name}(object):"elif self.name =="NXObject":yield lv *"\t"+f"class {self.name}(NXOpen.TaggedObject,NXOpen.INXObject):"else:yield lv *"\t"+f"class {self.name}(object):"for i in self.docs(lv):yield i for v in self.dcts():for ss in v.toStr(lv +1):yield ss for i, v in self.tpsinvoke.items(): _a =".".join(v)yield lv *"\t"+"\t"+f"{i}={_a}"classnxoType(pyibase):def__init__(self, m:type)->None:super().__init__()assertisinstance(m,type) self.doc = m.__doc__ self.name = m.__name__ self.mo =type.mro(m) self.sp = self.mo[1] ll =[]for k in self.mo[1:]:for s indir(k):ifnot s.startswith("_"): ll.append(s) self.addmember(m, ll)deftoStr(self, lv=0, mx=130):yield lv *"\t"+f"class {self.name}({str(self.sp)[8:-2]}):"for i in self.docs(lv):yield i for v in self.dcts():for i in v.toStr(lv +1):yield i for i, v in self.tpsinvoke.items(): _a =".".join(v)yield lv *"\t"+"\t"+f"{i}={_a}" pt1 =r":returns:[ \S]*[\n]?\s*:rtype: :py:class:`([\S]+)`" p1 = re.compile(pt1) pt2 =r":returns:[ \S]*[\n]?\s*:rtype: list of :py:class:`([\S]+)`" p2 = re.compile(pt2) pt3 =r":returns:[ \S]*[\n]?\s*:rtype: ([\S]+)" p3 = re.compile(pt3) pt4 =r":returns:[ \S]*[\n]?\s*:rtype: list of ([\S]+)" p4 = re.compile(pt4)deffindrtype(ss:str): rtp ="" r = p1.search(ss)if r isnotNone: rtp = r.groups()[0]if rtp =="": r = p2.search(ss)if r isnotNone: rtp =f"List[{r.groups()[0]}]"if rtp =="": r = p3.search(ss)if r isnotNone: rtp = r.groups()[0]if rtp notin["int","str","float","bool"]: rtp =""if rtp =="": r = p4.search(ss)if r isnotNone: rtp = r.groups()[0]if rtp notin["int","str","float","bool"]: rtp =""else: rtp =f"List[{rtp}]"return rtp classnxoMethodDescriptorType(pyibase):def__init__(self, m: types.MethodDescriptorType)->None:super().__init__()assertisinstance(m, types.MethodDescriptorType) self.doc = m.__doc__ self.name = m.__name__ deftoStr(self, lv:int=0, mx:int=130): rtp = findrtype(str(self.doc))if rtp =="": rr =""else: rr =f"->{rtp}"if self.name =="Dispose":yield lv *"\t"+f"def {self.name}(self){rr}:"else:yield lv *"\t"+f"def {self.name}(self,*args,**kw){rr}:"for i in self.docs(lv):yield i yield lv *"\t"+"\t"+"..."classnxoGetSetDescriptorType(pyibase):def__init__(self, m: types.GetSetDescriptorType)->None:super().__init__()assertisinstance(m, types.GetSetDescriptorType) self.doc = m.__doc__ self.name = m.__name__ deftoStr(self, lv:int=0, mx:int=130): rtp = findrtype(str(self.doc))yield lv *"\t"+f"@property"if rtp =="":yield lv *"\t"+f"def {self.name}(self):"else:yield lv *"\t"+f"def {self.name}(self)->{rtp}:"for i in self.docs(lv):yield i yield lv *"\t"+"\t"+"..."yield lv *"\t"+f"@{self.name}.setter"if rtp =="":yield lv *"\t"+f"def {self.name}(self,value):..."else:yield lv *"\t"+f"def {self.name}(self,value:{rtp}):..."yield""classnxoMemberDescriptorType(pyibase):def__init__(self, m: types.MemberDescriptorType)->None:super().__init__()assertisinstance(m, types.MemberDescriptorType) self.doc = m.__doc__ self.name = m.__name__ self._tp =type(m).__name__ deftoStr(self, lv:int=0, mx:int=130):yield lv *"\t"+f"{self.name}:{self._tp}=..."for i in self.docs(lv):yield i classnxoBuiltinFunctionType(pyibase):def__init__( self, m:"types.MemberDescriptorType |types.BuiltinMethodType", cname="")->None:super().__init__()assertisinstance(m, types.BuiltinFunctionType)andisinstance( m, types.BuiltinMethodType ) self.doc = m.__doc__ self.name = m.__name__ self.cname = cname deftoStr(self, lv:int=0, mx:int=130): rtp = findrtype(str(self.doc))yield lv *"\t"+f"@classmethod"if self.name =="ValueOf":yield lv *"\t"+f"def {self.name}(cls,value:int):"elif rtp !="":yield lv *"\t"+f"def {self.name}(cls,*args,**kw)->{rtp}:"elif self.cname !=""and self.name =="Get"+ self.cname:ifhasattr(NXOpen, self.cname):yield lv *"\t"+f"def {self.name}(cls,*args,**kw)->NXOpen.{self.cname}:"else:yield lv *"\t"+f"def {self.name}(cls,*args,**kw)->{self.cname}:"else:yield lv *"\t"+f"def {self.name}(cls,*args,**kw):"for i in self.docs(lv):yield i yield lv *"\t"+"\t"+"..."classnxoClsAliasType(pyibase):def__init__(self, m, name="")->None:super().__init__() _md = m.__class__.__module__ assert"NXOpen"instr(_md) self.doc = m.__doc__ self.name = m.__name__ ifhasattr(m,"__name__")else name self.attp =str(m.__class__.__name__) self.body = m deftoStr(self, lv=0, mx=130): nn = self.attp ifhasattr(NXOpen, nn): att =getattr(NXOpen, nn)ifisinstance(att,type): nn =f"NXOpen.{nn}"else: nn = self.body.__class__.__module__ +"."+ self.body.__class__.__name__ if self.name =="KeyPerformanceInterface":print(self.name,f"{self.name}:{nn}=...")yield lv *"\t"+f"{self.name}:{nn}=..."for i in self.docs(lv -1):yield i classmainModules(pyibase):def__init__( self,)->None:super().__init__() m = NXOpen self.doc = m.__doc__ self.name = m.__name__ self.addmember(m)for i in pyibase.ecpts: self.chdtps[i]= basetps(getattr(NXOpen, i), i)for k, v in imp_mds.items(): self.chdmdls[k]= nxoModuleType(v)defpyi(self): mm = self ifnot os.path.exists("./NXOpen/"): os.mkdir("./NXOpen")ifnot os.path.exists("./NXOpen/clss/"): os.mkdir("./NXOpen/clss/") p11 ="./NXOpen/" p22 = os.path.join(p11,"clss/")withopen(os.path.join(p11,"__init__.py"),"w", encoding="utf8")as f: m: nxoModuleType for v in mm.chdmdls.values(): m = v mn = m.name.split(".")[-1] mName = mn +".pyi"withopen(os.path.join(p11, mName),"w")as f2: f2.write("import NXOpen\n") f2.write("from typing import List\n")for _s in m.toStr(): f2.write(_s +"\n") f.write(f"from .{mn} import {mn} as {mn}"+"\n") f.write(f"from ._nxopen import *\n")withopen(os.path.join(p11,"_nxopen.pyi"),"w", encoding="utf8")as f2: m2: nxoType f2.write("import NXOpen\n") f2.write("from typing import List\n")for k, v in mm.chdtps.items(): m2 = v nn = m2.name f2.write(f"from .clss.{nn} import {nn} as {nn}"+"\n")withopen( os.path.join(p22,f"{nn}.pyi"),"w", encoding="utf8")as f3: f3.write("import NXOpen\n") f3.write("from typing import List\n")for _s in m2.toStr(): f3.write(f"{_s}\n")if __name__ =="__main__":defmain(): mainModules().pyi() main()

生成的NXOpen文件件放到这里:

在这里插入图片描述

已经可以正常提示了:

在这里插入图片描述

5 在NX中运行外部python

主要是两个环境变量的设置,修改NX1946\UGII\ugii_env.dat文件。

UGII_PYTHON_LIBRARY_DIR=“D:\Python37”

UGII_PYTHONPATH=D:\Python37;D:\Python37\DLLs;D:\Python37\Lib;D:\Python37\Lib\site-packages;D:\Python37\libs"D:\Siemens\NX 1946\NXBIN\python"

UGII_PYTHON_LIBRARY_DIR指向的是python37.dll文件所在的目录。

在这里插入图片描述

注:运行第三方库的时候需要在代码前增加#nx:threaded,可解决卡死问题。

Read more

【SpringBoot】——在做一些项目中所学到的新的技术栈和一些小技巧(主要为MQ,详细请看目录和文章)

【SpringBoot】——在做一些项目中所学到的新的技术栈和一些小技巧(主要为MQ,详细请看目录和文章)

🎼个人主页:【Y小夜】 😎作者简介:一位双非学校的大三学生,编程爱好者, 专注于基础和实战分享,欢迎私信咨询! 🎆入门专栏:🎇【MySQL,Java基础,Rust】 🎈热门专栏:🎊【Python,Javaweb,Springboot】  感谢您的点赞、关注、评论、收藏、是对我最大的认可和支持!❤️ 目录 🎈假删(逻辑删除) 🎈启动端口总是被占用 🎉和其他启动程序端口冲突 🎉 Hyper-V虚拟机 🎈文件上传校验 🎈分库分表 🎈限流机制 🎉 常见的限流算法 🎊固定窗口限流算法 🎊滑动窗口限流算法 🎊漏桶算法 🎊令牌桶算法 🎈异步化以及线程池 🎉 异步化 🎉 线程池   🎊线程池的作用   🎊线程池的实现 🎊任务类型 🎈消息队列 🎉 模型 🎉 优势 🎊应用解耦的优势 🎈RabbitMQ入门 🎉 安装 🎉 配置RabbitMQ 🎉 常用端口 🎉 入门程序 🎊Hello

By Ne0inhk
从 “渐进式披露” 到 “能力即文件”:Claude Agent Skills 的技术本质、架构变革与生态影响

从 “渐进式披露” 到 “能力即文件”:Claude Agent Skills 的技术本质、架构变革与生态影响

引言 人工智能(Artificial Intelligence,AI)智能体(Agent)技术正在经历从通用能力向专业化能力的范式转变。在这一变革浪潮中,Anthropic 于 2025 年 10 月发布的 Agent Skills 方法代表了 AI 能力扩展机制的一次重要创新。这项技术的核心价值在于,它通过一种基于文件系统的模块化架构,将领域专业知识封装为可复用的技能单元,使得通用大模型能够动态按需加载特定能力,从而在保持上下文效率的同时实现专业化任务执行。不同于传统的提示工程或工具调用模式,Agent Skills 采用 “渐进式披露” 的加载机制,仅在与任务相关时才将详细指令载入上下文窗口,这一设计有效解决了长期困扰 AI Agent 系统的上下文瓶颈问题。从企业实践来看,早期采用者已报告了显著的生产力提升,某医疗保健软件公司的 21 天试点项目记录了 49 个 AI 增强用例,累计节省超过 680 小时的工作时间。本报告将系统性地解构 Claude

By Ne0inhk
深入浅出 NVIDIA CUDA 架构与并行计算技术

深入浅出 NVIDIA CUDA 架构与并行计算技术

🐇明明跟你说过:个人主页 🏅个人专栏:《深度探秘:AI界的007》 🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、CUDA为何重要:并行计算的时代 2、NVIDIA在GPU计算领域的角色 二、CUDA简介 1、什么是CUDA 2、CUDA的历史与发展 三、CUDA架构解析 1、GPU vs CPU:架构对比 2、CUDA核心组件 四、CUDA编程模型 1、CUDA程序的基本结构 2、Kernel函数与线程层级 3、内存管理与数据传输(Host ↔ Device) 一、引言 1、CUDA为何重要:并行计算的时代 🧠 单核时代的终结 曾几何时,我们对计算性能的追求是这样的: “CPU 主频越高越好,

By Ne0inhk
一文看懂 Modbus RTU 协议:核心架构、报文解析与现场调试避坑指

一文看懂 Modbus RTU 协议:核心架构、报文解析与现场调试避坑指

目录 一、 核心架构:主从式结构 (Client/Server) 二、 常见传输模式:RTU 与 TCP 三、 数据模型:四类存储寄存器 四、 常用功能码 (Function Codes) 五、 报文结构示例 (Modbus RTU) 六、 常见问题与排查思路 一、 核心架构:主从式结构 (Client/Server) Modbus 采用典型的主从式通信模型: 主站 (Master/Client):唯一的指令发起方,同一网络内同一时刻仅存在一台主站,负责主动查询从站数据 / 下发控制指令; 从站 (Slave/Server):指令被动响应方,每台从站配备唯一站号(ID),仅在被主站点名调用时反馈数据 / 执行指令,无主动发送数据的权限; * 注意: 从站不会主动发送数据,只有在被主站“

By Ne0inhk