NXOpen Python API 二次开发环境配置
前言
最近在工作中遇到一些 NX 二次开发的工作,有一些深度学习与 NX 交互的工作内容,尝试使用 Python 进行二次开发。在网上搜索了几个环境配置的教程,都没有实现代码提示的功能,最近找到生成.pyi 文件的方法才实现了代码提示功能,把完整的配置流程分享给大家。
1 安装 NX 和对应版本的 Python
1)在 NX 安装目录下找到 python37.dll 文件,查看文件属性。如安装的是 NX1946,可以查看到对应的 Python 版本是 3.7.5。
![图片]
2)下载对应的 Python 版本安装到将要用于项目开发的文件夹中,直接使用安装环境,避免虚拟环境的各种问题。如直接安装在 D:\NXOpenPython 中。
2 添加 nxopen 库
1)在 D:\NXOpenPython\python37\Lib\site-packages 目录中新建一个 nxopen.pth 的文件,在文件中添加 NXBIN 下的 python 路径。
2)添加 UGII 目录到系统变量 PATH 下。
PATH = D:\安装目录\NX1946\UGII; D:\安装目录\NX1946\NXBIN\
3)进入 IDLE 进行测试。
![图片]
![图片]
3 在 PyCharm 中新建项目
1)Python 解释器使用刚安装的 Python,并添加 NXBIN 目录。
![图片]
![图片]
已经能调用 NXOpen 的 API 了,但是只能提示到安装包,没有函数提示功能。
![图片]
4 IDE 中实现代码提示功能
PyCharm 本身并不直接'解析' .pyd 文件(Windows 下的 Python 扩展模块,本质上是 DLL 文件),因为 .pyd 是编译后的二进制文件,不是源代码。但如果你希望在 PyCharm 中获得代码补全、类型提示、跳转定义等 IDE 功能支持,那么你需要采取一些额外措施,因为 PyCharm 无法从 .pyd 文件中读取函数签名或文档。
为了让 PyCharm 提供智能提示(自动补全、参数提示、跳转等),你需要提供类型存根(stub files),即 .pyi 文件。
- 先运行下面的代码,生成 NXOpen 文件夹。
- 再把这个文件夹移动到 NXBIN/python 目录下。
__version__ = "0.0.4"
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:
ff files:
(ff).startswith() (ff).endswith():
module_name = (ff)[:-]
:
ms = module_name.split()[-]
imp_mds[ms] = import_module(module_name)
Exception e:
(, module_name, e)
:
ecpts = [, , ]
() -> :
.name: =
.doc: [] =
.chdmdls: = {}
.chdtps: = {}
.MdDescriptor: = {}
.GSDescriptor: = {}
.unct: = {}
.nxc: [, ] = {}
.mthdorbutin: = {}
.mberDescriptor: = {}
.tpsinvoke: [, ] = {}
.nn: [] = []
() -> Generator[, , ]:
dc [.chdmdls, .chdtps, .MdDescriptor, .GSDescriptor, .unct, .nxc, .mthdorbutin, .mberDescriptor]:
v dc.values():
v
():
dirm = (m)
dm :
dirm = [i i dirm i dm]
i dirm:
i == :
(i)
i.startswith():
att = (m, i)
.nn.append(i)
(att, types.ModuleType):
.chdmdls[i] = nxoModuleType(att)
(att, ):
i != att.__name__:
.tpsinvoke[i] = [att.__module__, att.__name__]
i pyibase.ecpts:
.chdtps[i] = nxoType(att)
(att, types.MethodDescriptorType):
.MdDescriptor[i] = nxoMethodDescriptorType(att)
(att, types.GetSetDescriptorType):
.GSDescriptor[i] = nxoGetSetDescriptorType(att)
(att, types.MemberDescriptorType):
.mberDescriptor[i] = nxoMemberDescriptorType(att)
:
_md = att.__class__.__module__
(_md):
.nxc[i] = nxoClsAliasType(att, i)
i == :
.mthdorbutin[i] = nxoBuiltinFunctionType(att)
(att, types.BuiltinFunctionType):
.mthdorbutin[i] = nxoBuiltinFunctionType(att, cname=.name)
:
TypeError(i, att, (att))
():
dd = (.doc)
dd = dd.strip()
dd2 = dd.splitlines()
dd2 = [i.strip() i dd2]
ll = mx - lv *
(lv + ) * +
(lv + ) * +
i dd2:
k (, (i), ll):
(lv + ) * + i[k:((i), k + ll)]
(lv + ) * +
():
lv * +
():
() -> :
().__init__()
(m, types.ModuleType)
.doc = m.__doc__
.name = m.__name__.split()[-]
.addmember(m)
():
lv * +
i .docs(lv):
i
dc .dcts():
i dc.toStr(lv + ):
i
i, v .tpsinvoke.items():
_a = .join(v)
+
():
() -> :
().__init__()
name pyibase.ecpts
.name = name
.doc = m.__doc__
.mo = .mro(m)
.addmember(m)
():
.name [, ]:
lv * +
.name == :
lv * +
:
lv * +
i .docs(lv):
i
v .dcts():
ss v.toStr(lv + ):
ss
i, v .tpsinvoke.items():
_a = .join(v)
lv * + +
():
() -> :
().__init__()
(m, )
.doc = m.__doc__
.name = m.__name__
.mo = .mro(m)
.sp = .mo[]
ll = []
k .mo[:]:
s (k):
s.startswith():
ll.append(s)
.addmember(m, ll)
():
lv * +
i .docs(lv):
i
v .dcts():
i v.toStr(lv + ):
i
i, v .tpsinvoke.items():
_a = .join(v)
lv * + +
pt1 =
p1 = re.(pt1)
pt2 =
p2 = re.(pt2)
pt3 =
p3 = re.(pt3)
pt4 =
p4 = re.(pt4)
():
rtp =
r = p1.search(ss)
r :
rtp = r.groups()[]
rtp == :
r = p2.search(ss)
r :
rtp =
rtp == :
r = p3.search(ss)
r :
rtp = r.groups()[]
rtp [, , , ]:
rtp =
rtp == :
r = p4.search(ss)
r :
rtp = r.groups()[]
rtp [, , , ]:
rtp =
:
rtp =
rtp
():
() -> :
().__init__()
(m, types.MethodDescriptorType)
.doc = m.__doc__
.name = m.__name__
():
rtp = findrtype((.doc))
rtp == :
rr =
:
rr =
.name == :
lv * +
:
lv * +
i .docs(lv):
i
lv * + +
():
() -> :
().__init__()
(m, types.GetSetDescriptorType)
.doc = m.__doc__
.name = m.__name__
():
rtp = findrtype((.doc))
lv * +
rtp == :
lv * +
:
lv * +
i .docs(lv):
i
lv * + +
lv * +
rtp == :
lv * +
:
lv * +
():
() -> :
().__init__()
(m, types.MemberDescriptorType)
.doc = m.__doc__
.name = m.__name__
._tp = (m).__name__
():
lv * +
i .docs(lv):
i
():
() -> :
().__init__()
(m, types.BuiltinFunctionType) (m, types.BuiltinMethodType)
.doc = m.__doc__
.name = m.__name__
.cname = cname
():
rtp = findrtype((.doc))
lv * +
.name == :
lv * +
rtp != :
lv * +
.cname != .name == + .cname:
(NXOpen, .cname):
lv * +
:
lv * +
:
lv * +
i .docs(lv):
i
lv * + +
():
() -> :
().__init__()
_md = m.__class__.__module__
(_md)
.doc = m.__doc__
.name = m.__name__ (m, ) name
.attp = (m.__class__.__name__)
.body = m
():
nn = .attp
(NXOpen, nn):
att = (NXOpen, nn)
(att, ):
nn =
:
nn = .body.__class__.__module__ + + .body.__class__.__name__
.name == :
(.name, )
lv * +
i .docs(lv - ):
i
():
() -> :
().__init__()
m = NXOpen
.doc = m.__doc__
.name = m.__name__
.addmember(m)
i pyibase.ecpts:
.chdtps[i] = basetps((NXOpen, i), i)
k, v imp_mds.items():
.chdmdls[k] = nxoModuleType(v)
():
mm =
os.path.exists():
os.mkdir()
os.path.exists():
os.mkdir()
p11 =
p22 = os.path.join(p11, )
(os.path.join(p11, ), , encoding=) f:
m: nxoModuleType
v mm.chdmdls.values():
m = v
mn = m.name.split()[-]
mName = mn +
(os.path.join(p11, mName), ) f2:
f2.write()
f2.write()
_s m.toStr():
f2.write(_s + )
f.write()
f.write()
(os.path.join(p11, ), , encoding=) f2:
m2: nxoType
f2.write()
f2.write()
k, v mm.chdtps.items():
m2 = v
nn = m2.name
f2.write()
(os.path.join(p22, ), , encoding=) f3:
f3.write()
f3.write()
_s m2.toStr():
f3.write()
__name__ == :
():
mainModules().pyi()
main()


