如何通过二次开发Python为UG添加特定螺纹规格?

2026-05-05 16:072阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1846个文字,预计阅读时间需要8分钟。

如何通过二次开发Python为UG添加特定螺纹规格?

NX+1988系列在添加纹理特征时,无法自定义纹理规格,需从网上查找资料讲解。改用XML文件,在文件中添加自定义纹理规格,从而实现所需效果。编写小程序方便操作。

NX 1988 系列 在添加螺纹特征时,不能自定义螺纹规格,

从网上找到的资料上讲,改一个XML文件,在文件中添加自定义的螺纹规格,从而实现需要的效果。
自己写了一个小程序,方便手动添加螺纹规格。

效果图

上代码

# nx: threaded from typing import List import os from bs4 import BeautifulSoup as bs import bs4 from PySide6 import QtCore as qc from PySide6 import QtWidgets as qw from PySide6 import QtGui as qg os.chdir(os.path.dirname(os.path.abspath(__file__))) r_path = "" w_path = "" class mw(qw.QDialog): def __init__(self) -> None: super().__init__() self.ly_main = qw.QHBoxLayout(self) """主框架""" self.ly_left = qw.QHBoxLayout() """左 主 框架""" self.ly_left_up = qw.QVBoxLayout() """左 上 框架""" self.ly_left_down = qw.QVBoxLayout() """左 下 框架""" self.ly_mid = qw.QVBoxLayout() """中 主 框架""" self.ly_right = qw.QVBoxLayout() """右 主 框架""" self.ly_left_down.addLayout(self.ly_left_up, 0) self.ly_left_down.addLayout(self.ly_left, 1) self.lb_show = qw.QLabel("start") self.ly_left_up.addWidget(self.lb_show, 1) self.static_lb_1 = qw.QLabel("Unit") self.cb_unit = qw.QComboBox(self) self.cb_unit.addItems(["Metric", "Inch"]) self.cb_unit.currentIndexChanged.connect(self.on_cb_unit_change) self.ly_left_up.addWidget(self.static_lb_1, 1) self.ly_left_up.addWidget(self.cb_unit, 1) self.static_lb_2 = qw.QLabel("Standard") self.cb_standard = qw.QComboBox(self) self.cb_standard.currentIndexChanged.connect(self.on_cb_standard_change) self.ly_left_up.addWidget(self.static_lb_2, 1) self.ly_left_up.addWidget(self.cb_standard, 1) self.static_lb_3 = qw.QLabel("Size") self.cb_size = qw.QComboBox(self) self.cb_size.currentIndexChanged.connect(self.on_cb_size_change) self.ly_left_up.addWidget(self.static_lb_3, 1) self.ly_left_up.addWidget(self.cb_size, 1) self.lb_show_name = qw.QLabel("") self.ly_left_up.addWidget(self.lb_show_name, 1) self.mm = qw.QLineEdit() self.pp = qw.QLineEdit() self.bt_copy = qw.QPushButton("复制") self.bt_insert = qw.QPushButton("插入") self.bt_save = qw.QPushButton("保存") self.bt_edit = qw.QPushButton("修改") self.bt_copy.clicked.connect(self.on_bt_copy_click) self.bt_insert.clicked.connect(self.on_bt_insert_click) self.bt_save.clicked.connect(self.on_bt_save_click) self.bt_edit.clicked.connect(self.on_bt_edit_click) self.ly_left_up.addWidget(self.bt_copy) self.ly_left_up.addWidget(qw.QLabel("螺径")) self.ly_left_up.addWidget(self.mm) self.ly_left_up.addWidget(qw.QLabel("螺距")) self.ly_left_up.addWidget(self.pp) self.ly_left_up.addWidget(self.bt_edit) self.ly_left_up.addWidget(self.bt_insert) self.ly_left_up.addWidget(self.bt_save) self.tb_mid = qw.QTableWidget(40, 2, self) self.tb_mid.setHorizontalHeaderLabels(["属性", "值"]) self.ly_mid.addWidget(qw.QLabel("原始数据")) self.ly_mid.addWidget(self.tb_mid) self.tb_right = qw.QTableWidget(40, 2, self) self.tb_right.setHorizontalHeaderLabels(["属性", "值"]) self.ly_right.addWidget(qw.QLabel("修改数据")) self.ly_right.addWidget(self.tb_right) self.scrollbar_mid = self.tb_mid.verticalScrollBar() self.scrollbar_right = self.tb_right.verticalScrollBar() self.scrollbar_mid.valueChanged.connect(self.on_tb_mid_scroll) self.scrollbar_right.valueChanged.connect(self.on_tb_right_scroll) self.setLayout(self.ly_main) self.ly_main.addLayout(self.ly_left_down) self.ly_main.addLayout(self.ly_mid) self.ly_main.addLayout(self.ly_right) self.resize(900, 600) x = thread_xml_reader() r = x.read_xml(r_path) rot = next(r.children) nds2 = [] for i in rot.children: if isinstance(i, bs4.element.NavigableString) and len(str(i).strip()) == 0: pass else: nds2.append(i) self.rt = hole_root(nds2) self.tgs: List[bs4.element.Tag] = [] self.crt = 0 self.cb_size_lst = [] self._crt_unit = "" self._crt_standard = "" self.crt_unit = "Metric" self.crt_data: bs4.element.Tag = None self.copyed_tg: bs4.element.Tag = None self.crt = 0 @property def crt(self): """当前序号""" return self._crt @crt.setter def crt(self, value): self._crt = value if self._crt < 0: self.lb_show_name.setText("start") elif self._crt >= len(self.tgs): self.lb_show_name.setText("over") else: self.lb_show_name.setText(f"current: {self._crt}, next =>") self.cb_size.setCurrentIndex(self._crt) if self._crt >= len(self.tgs): self.tb_mid.clearContents() self.lb_show_name.setText("") self.lb_show.setText("over") else: tg = self.tgs[self._crt] attrs = tg.attrs self.lb_show_name.setText(tg.name) self.lb_show.setText(f"当前 {self._crt} next->") i = 0 for k, v in attrs.items(): item = qw.QTableWidgetItem(str(k)) self.tb_mid.setItem(i, 0, item) item = qw.QTableWidgetItem(f"{str(v)}") self.tb_mid.setItem(i, 1, item) i += 1 self.crt_data = tg @property def crt_unit(self) -> str: """当前的系列 Metric Inch""" return self._crt_unit @crt_unit.setter def crt_unit(self, value): if value == self._crt_unit: pass else: self._crt_unit = value self.cb_standard.clear() if value == "Metric": rr = self.rt.metric elif value == "Inch": rr = self.rt.inch else: return self.cb_size_lst = rr.ssnames self.cb_standard.addItems(rr.ssnames) @property def crt_standard(self): """当前标号""" return self._crt_standard @crt_standard.setter def crt_standard(self, value): if value == self._crt_standard: pass else: self._crt_standard = value vv = self.cb_unit.currentText() if vv == "Metric": rr = self.rt.metric elif vv == "Inch": rr = self.rt.inch vvs = self.cb_standard.currentText() if vvs == "": vvs = self.cb_size_lst[0] r3: hole_standard = None for i in rr.ss: if i.standard == vvs: r3 = i break if r3 != None: self.tgs = r3.holes xx = [i.attrs["Size"] for i in self.tgs] self.cb_size.clear() self.cb_size.addItems(xx) self.crt = 0 def on_cb_unit_change(self): self.crt_unit = self.cb_unit.currentText() def on_cb_standard_change(self): self.crt_standard = self.cb_standard.currentText() def on_cb_size_change(self): idx = self.cb_size.currentIndex() if idx != self._crt: self.crt = idx def on_bt_copy_click(self) -> None: attrs = self.crt_data.attrs.copy() attrs["Standard"] = "User" self.copyed_tg = bs4.element.Tag( attrs=attrs, name=self.crt_data.name, can_be_empty_element=True ) attrs = self.copyed_tg.attrs self.toTb3() def on_bt_insert_click(self) -> None: ss = self.rt.metric.user.hole_sizes if self.copyed_tg is None: return else: tg_size = self.copyed_tg.attrs["Size"] if tg_size not in ss: self.rt.metric.user.holes.append(self.copyed_tg) self.rt.metric.user.holes.sort( key=lambda x: float(x.attrs["Size"][1:].split(" ")[0]) ) ss = self.rt.metric.user.hole_sizes ct = -1 for i in range(len(ss)): if ss[i] == tg_size: ct = i break self.cb_unit.setCurrentText("Metric") self.cb_standard.setCurrentText("User") self.crt = ct def on_bt_save_click(self) -> None: if w_path != "": with open(w_path, "w") as f: for i in self.rt.toStr(): f.write(i) def toTb3(self): """更新表3""" if self.copyed_tg is not None: attrs = self.copyed_tg.attrs i = 0 for k, v in attrs.items(): item1 = qw.QTableWidgetItem(str(k)) self.tb_right.setItem(i, 0, item1) item2 = qw.QTableWidgetItem(f"{str(v)}") self.tb_right.setItem(i, 1, item2) i += 1 if k == "Standard": item2.setFlags(item2.flags() ^ qc.Qt.ItemIsEditable) def on_bt_edit_click(self) -> None: mmm = 0 ppp = 0 if self.copyed_tg is None: return tt = self.tb_right.item(1, 1).text() if tt != "Metric": return try: mmm = int(self.mm.text()) ppp = round(float(self.pp.text()), 2) except: pass if mmm <= 0 or ppp <= 0: return self.copyed_tg.attrs["Size"] = f"M{mmm} x {ppp}" self.copyed_tg.attrs["ScrewSize"] = f"M{mmm}" self.copyed_tg.attrs["MajorDiameter"] = f"{mmm}" self.copyed_tg.attrs["MinorDiameter"] = f"{round(mmm-ppp,3)}" self.copyed_tg.attrs["TapDrillDia"] = f"{round(mmm-ppp+0.01,1)}" self.copyed_tg.attrs["ShaftDiameter"] = f"{mmm}" self.copyed_tg.attrs["Pitch"] = f"{ppp}" self.copyed_tg.attrs["Callout"] = f"M{mmm}_x_{ppp}" self.copyed_tg.attrs["HoleDepth"] = f"{mmm*2}" self.copyed_tg.attrs["ThreadDepth"] = f"{int(mmm*1.5)}" self.copyed_tg.attrs["ReliefDiameter"] = f"{float(mmm):0.3f}" self.copyed_tg.attrs["ReliefDepth"] = f"{mmm*0.5:0.3f}" self.copyed_tg.attrs["ReliefChamferOffset"] = f"{round(ppp*1.1,1):0.3f}" self.copyed_tg.attrs["StartChamferDiameter"] = f"{float(mmm):0.3f}" self.copyed_tg.attrs["EndChamferDiameter"] = f"{float(mmm):0.3f}" self.toTb3() def on_tb_mid_scroll(self, e): self.tb_right.verticalScrollBar().setValue(e) def on_tb_right_scroll(self, e): self.tb_mid.verticalScrollBar().setValue(e) class thread_xml_reader: def __init__(self) -> None: pass def read_xml(self, rpath: str): if os.path.exists(rpath): with open(rpath, "r", encoding="utf8") as f: soup = bs(f, "lxml-xml") return soup class hole_root: def __init__(self, hs: List[bs4.element.Tag]) -> None: met = [] icht = [] for i in hs: if i.attrs["Unit"] == "Metric": met.append(i) elif i.attrs["Unit"] == "Inch": icht.append(i) self.metric = hole_metric(met) self.inch = hole_inch(icht) def toStr(self): yield """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n""" yield "<root>\n" for i in self.inch.ss: for k in i.holes: kas = k.attrs r = " <" + k.name for k, v in kas.items(): r += f' {k}="{v}"' r += " />\n" yield r for i in self.metric.ss: for k in i.holes: kas = k.attrs r = " <" + k.name for k, v in kas.items(): r += f' {k}="{v}"' r += " />\n" yield r yield "</root>" class hole_metric: """Metric""" unit = "Metric" def __init__(self, hs: List[bs4.element.Tag]) -> None: rr = {} nn = [] for i in hs: s = i.attrs["Standard"] if s in nn: rr[s].append(i) else: nn.append(s) rr[s] = [i] self.ss: List[hole_standard] = [hole_standard(k, v) for k, v in rr.items()] for i in self.ss: if i.standard == "User": self.user = i break else: self.user = hole_standard("User", []) self.ss.append(self.user) @property def ssnames(self): return [i.standard for i in self.ss] class hole_inch: """Inch""" unit = "Inch" def __init__(self, hs: List[bs4.element.Tag]) -> None: rr = {} nn = [] for i in hs: s = i.attrs["Standard"] if s in nn: rr[s].append(i) else: nn.append(s) rr[s] = [i] self.ss = [hole_standard(k, v) for k, v in rr.items()] @property def ssnames(self): return [i.standard for i in self.ss] class hole_standard: "standard" def __init__(self, name: str, hs: List[bs4.element.Tag]) -> None: self.standard = name self.holes = hs @property def hole_sizes(self) -> List[str]: return [i.attrs["Size"] for i in self.holes] def main(): app = qw.QApplication() mm = mw() mm.show() app.exec() exit() if __name__ == "__main__": ug_base_dir = os.getenv("UGII_BASE_DIR") if ug_base_dir is None or ug_base_dir == "": pass else: file_dir = os.path.join(ug_base_dir, "UGII", "modeling_standards") w_path = r_path = os.path.join(file_dir, "NX_Thread_Standard.xml") backup_path = os.path.join(file_dir, "NX_Thread_Standard_bak.xml") if not os.path.exists(r_path): raise FileNotFoundError(r_path) if not os.path.exists(backup_path): import shutil shutil.copy(r_path, backup_path) main() 没有写删除的功能,怕不小心误操作,要删除某一个规格的话,自己打开 相应的XML文件,手动删除行就行了

如何通过二次开发Python为UG添加特定螺纹规格?

本文共计1846个文字,预计阅读时间需要8分钟。

如何通过二次开发Python为UG添加特定螺纹规格?

NX+1988系列在添加纹理特征时,无法自定义纹理规格,需从网上查找资料讲解。改用XML文件,在文件中添加自定义纹理规格,从而实现所需效果。编写小程序方便操作。

NX 1988 系列 在添加螺纹特征时,不能自定义螺纹规格,

从网上找到的资料上讲,改一个XML文件,在文件中添加自定义的螺纹规格,从而实现需要的效果。
自己写了一个小程序,方便手动添加螺纹规格。

效果图

上代码

# nx: threaded from typing import List import os from bs4 import BeautifulSoup as bs import bs4 from PySide6 import QtCore as qc from PySide6 import QtWidgets as qw from PySide6 import QtGui as qg os.chdir(os.path.dirname(os.path.abspath(__file__))) r_path = "" w_path = "" class mw(qw.QDialog): def __init__(self) -> None: super().__init__() self.ly_main = qw.QHBoxLayout(self) """主框架""" self.ly_left = qw.QHBoxLayout() """左 主 框架""" self.ly_left_up = qw.QVBoxLayout() """左 上 框架""" self.ly_left_down = qw.QVBoxLayout() """左 下 框架""" self.ly_mid = qw.QVBoxLayout() """中 主 框架""" self.ly_right = qw.QVBoxLayout() """右 主 框架""" self.ly_left_down.addLayout(self.ly_left_up, 0) self.ly_left_down.addLayout(self.ly_left, 1) self.lb_show = qw.QLabel("start") self.ly_left_up.addWidget(self.lb_show, 1) self.static_lb_1 = qw.QLabel("Unit") self.cb_unit = qw.QComboBox(self) self.cb_unit.addItems(["Metric", "Inch"]) self.cb_unit.currentIndexChanged.connect(self.on_cb_unit_change) self.ly_left_up.addWidget(self.static_lb_1, 1) self.ly_left_up.addWidget(self.cb_unit, 1) self.static_lb_2 = qw.QLabel("Standard") self.cb_standard = qw.QComboBox(self) self.cb_standard.currentIndexChanged.connect(self.on_cb_standard_change) self.ly_left_up.addWidget(self.static_lb_2, 1) self.ly_left_up.addWidget(self.cb_standard, 1) self.static_lb_3 = qw.QLabel("Size") self.cb_size = qw.QComboBox(self) self.cb_size.currentIndexChanged.connect(self.on_cb_size_change) self.ly_left_up.addWidget(self.static_lb_3, 1) self.ly_left_up.addWidget(self.cb_size, 1) self.lb_show_name = qw.QLabel("") self.ly_left_up.addWidget(self.lb_show_name, 1) self.mm = qw.QLineEdit() self.pp = qw.QLineEdit() self.bt_copy = qw.QPushButton("复制") self.bt_insert = qw.QPushButton("插入") self.bt_save = qw.QPushButton("保存") self.bt_edit = qw.QPushButton("修改") self.bt_copy.clicked.connect(self.on_bt_copy_click) self.bt_insert.clicked.connect(self.on_bt_insert_click) self.bt_save.clicked.connect(self.on_bt_save_click) self.bt_edit.clicked.connect(self.on_bt_edit_click) self.ly_left_up.addWidget(self.bt_copy) self.ly_left_up.addWidget(qw.QLabel("螺径")) self.ly_left_up.addWidget(self.mm) self.ly_left_up.addWidget(qw.QLabel("螺距")) self.ly_left_up.addWidget(self.pp) self.ly_left_up.addWidget(self.bt_edit) self.ly_left_up.addWidget(self.bt_insert) self.ly_left_up.addWidget(self.bt_save) self.tb_mid = qw.QTableWidget(40, 2, self) self.tb_mid.setHorizontalHeaderLabels(["属性", "值"]) self.ly_mid.addWidget(qw.QLabel("原始数据")) self.ly_mid.addWidget(self.tb_mid) self.tb_right = qw.QTableWidget(40, 2, self) self.tb_right.setHorizontalHeaderLabels(["属性", "值"]) self.ly_right.addWidget(qw.QLabel("修改数据")) self.ly_right.addWidget(self.tb_right) self.scrollbar_mid = self.tb_mid.verticalScrollBar() self.scrollbar_right = self.tb_right.verticalScrollBar() self.scrollbar_mid.valueChanged.connect(self.on_tb_mid_scroll) self.scrollbar_right.valueChanged.connect(self.on_tb_right_scroll) self.setLayout(self.ly_main) self.ly_main.addLayout(self.ly_left_down) self.ly_main.addLayout(self.ly_mid) self.ly_main.addLayout(self.ly_right) self.resize(900, 600) x = thread_xml_reader() r = x.read_xml(r_path) rot = next(r.children) nds2 = [] for i in rot.children: if isinstance(i, bs4.element.NavigableString) and len(str(i).strip()) == 0: pass else: nds2.append(i) self.rt = hole_root(nds2) self.tgs: List[bs4.element.Tag] = [] self.crt = 0 self.cb_size_lst = [] self._crt_unit = "" self._crt_standard = "" self.crt_unit = "Metric" self.crt_data: bs4.element.Tag = None self.copyed_tg: bs4.element.Tag = None self.crt = 0 @property def crt(self): """当前序号""" return self._crt @crt.setter def crt(self, value): self._crt = value if self._crt < 0: self.lb_show_name.setText("start") elif self._crt >= len(self.tgs): self.lb_show_name.setText("over") else: self.lb_show_name.setText(f"current: {self._crt}, next =>") self.cb_size.setCurrentIndex(self._crt) if self._crt >= len(self.tgs): self.tb_mid.clearContents() self.lb_show_name.setText("") self.lb_show.setText("over") else: tg = self.tgs[self._crt] attrs = tg.attrs self.lb_show_name.setText(tg.name) self.lb_show.setText(f"当前 {self._crt} next->") i = 0 for k, v in attrs.items(): item = qw.QTableWidgetItem(str(k)) self.tb_mid.setItem(i, 0, item) item = qw.QTableWidgetItem(f"{str(v)}") self.tb_mid.setItem(i, 1, item) i += 1 self.crt_data = tg @property def crt_unit(self) -> str: """当前的系列 Metric Inch""" return self._crt_unit @crt_unit.setter def crt_unit(self, value): if value == self._crt_unit: pass else: self._crt_unit = value self.cb_standard.clear() if value == "Metric": rr = self.rt.metric elif value == "Inch": rr = self.rt.inch else: return self.cb_size_lst = rr.ssnames self.cb_standard.addItems(rr.ssnames) @property def crt_standard(self): """当前标号""" return self._crt_standard @crt_standard.setter def crt_standard(self, value): if value == self._crt_standard: pass else: self._crt_standard = value vv = self.cb_unit.currentText() if vv == "Metric": rr = self.rt.metric elif vv == "Inch": rr = self.rt.inch vvs = self.cb_standard.currentText() if vvs == "": vvs = self.cb_size_lst[0] r3: hole_standard = None for i in rr.ss: if i.standard == vvs: r3 = i break if r3 != None: self.tgs = r3.holes xx = [i.attrs["Size"] for i in self.tgs] self.cb_size.clear() self.cb_size.addItems(xx) self.crt = 0 def on_cb_unit_change(self): self.crt_unit = self.cb_unit.currentText() def on_cb_standard_change(self): self.crt_standard = self.cb_standard.currentText() def on_cb_size_change(self): idx = self.cb_size.currentIndex() if idx != self._crt: self.crt = idx def on_bt_copy_click(self) -> None: attrs = self.crt_data.attrs.copy() attrs["Standard"] = "User" self.copyed_tg = bs4.element.Tag( attrs=attrs, name=self.crt_data.name, can_be_empty_element=True ) attrs = self.copyed_tg.attrs self.toTb3() def on_bt_insert_click(self) -> None: ss = self.rt.metric.user.hole_sizes if self.copyed_tg is None: return else: tg_size = self.copyed_tg.attrs["Size"] if tg_size not in ss: self.rt.metric.user.holes.append(self.copyed_tg) self.rt.metric.user.holes.sort( key=lambda x: float(x.attrs["Size"][1:].split(" ")[0]) ) ss = self.rt.metric.user.hole_sizes ct = -1 for i in range(len(ss)): if ss[i] == tg_size: ct = i break self.cb_unit.setCurrentText("Metric") self.cb_standard.setCurrentText("User") self.crt = ct def on_bt_save_click(self) -> None: if w_path != "": with open(w_path, "w") as f: for i in self.rt.toStr(): f.write(i) def toTb3(self): """更新表3""" if self.copyed_tg is not None: attrs = self.copyed_tg.attrs i = 0 for k, v in attrs.items(): item1 = qw.QTableWidgetItem(str(k)) self.tb_right.setItem(i, 0, item1) item2 = qw.QTableWidgetItem(f"{str(v)}") self.tb_right.setItem(i, 1, item2) i += 1 if k == "Standard": item2.setFlags(item2.flags() ^ qc.Qt.ItemIsEditable) def on_bt_edit_click(self) -> None: mmm = 0 ppp = 0 if self.copyed_tg is None: return tt = self.tb_right.item(1, 1).text() if tt != "Metric": return try: mmm = int(self.mm.text()) ppp = round(float(self.pp.text()), 2) except: pass if mmm <= 0 or ppp <= 0: return self.copyed_tg.attrs["Size"] = f"M{mmm} x {ppp}" self.copyed_tg.attrs["ScrewSize"] = f"M{mmm}" self.copyed_tg.attrs["MajorDiameter"] = f"{mmm}" self.copyed_tg.attrs["MinorDiameter"] = f"{round(mmm-ppp,3)}" self.copyed_tg.attrs["TapDrillDia"] = f"{round(mmm-ppp+0.01,1)}" self.copyed_tg.attrs["ShaftDiameter"] = f"{mmm}" self.copyed_tg.attrs["Pitch"] = f"{ppp}" self.copyed_tg.attrs["Callout"] = f"M{mmm}_x_{ppp}" self.copyed_tg.attrs["HoleDepth"] = f"{mmm*2}" self.copyed_tg.attrs["ThreadDepth"] = f"{int(mmm*1.5)}" self.copyed_tg.attrs["ReliefDiameter"] = f"{float(mmm):0.3f}" self.copyed_tg.attrs["ReliefDepth"] = f"{mmm*0.5:0.3f}" self.copyed_tg.attrs["ReliefChamferOffset"] = f"{round(ppp*1.1,1):0.3f}" self.copyed_tg.attrs["StartChamferDiameter"] = f"{float(mmm):0.3f}" self.copyed_tg.attrs["EndChamferDiameter"] = f"{float(mmm):0.3f}" self.toTb3() def on_tb_mid_scroll(self, e): self.tb_right.verticalScrollBar().setValue(e) def on_tb_right_scroll(self, e): self.tb_mid.verticalScrollBar().setValue(e) class thread_xml_reader: def __init__(self) -> None: pass def read_xml(self, rpath: str): if os.path.exists(rpath): with open(rpath, "r", encoding="utf8") as f: soup = bs(f, "lxml-xml") return soup class hole_root: def __init__(self, hs: List[bs4.element.Tag]) -> None: met = [] icht = [] for i in hs: if i.attrs["Unit"] == "Metric": met.append(i) elif i.attrs["Unit"] == "Inch": icht.append(i) self.metric = hole_metric(met) self.inch = hole_inch(icht) def toStr(self): yield """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n""" yield "<root>\n" for i in self.inch.ss: for k in i.holes: kas = k.attrs r = " <" + k.name for k, v in kas.items(): r += f' {k}="{v}"' r += " />\n" yield r for i in self.metric.ss: for k in i.holes: kas = k.attrs r = " <" + k.name for k, v in kas.items(): r += f' {k}="{v}"' r += " />\n" yield r yield "</root>" class hole_metric: """Metric""" unit = "Metric" def __init__(self, hs: List[bs4.element.Tag]) -> None: rr = {} nn = [] for i in hs: s = i.attrs["Standard"] if s in nn: rr[s].append(i) else: nn.append(s) rr[s] = [i] self.ss: List[hole_standard] = [hole_standard(k, v) for k, v in rr.items()] for i in self.ss: if i.standard == "User": self.user = i break else: self.user = hole_standard("User", []) self.ss.append(self.user) @property def ssnames(self): return [i.standard for i in self.ss] class hole_inch: """Inch""" unit = "Inch" def __init__(self, hs: List[bs4.element.Tag]) -> None: rr = {} nn = [] for i in hs: s = i.attrs["Standard"] if s in nn: rr[s].append(i) else: nn.append(s) rr[s] = [i] self.ss = [hole_standard(k, v) for k, v in rr.items()] @property def ssnames(self): return [i.standard for i in self.ss] class hole_standard: "standard" def __init__(self, name: str, hs: List[bs4.element.Tag]) -> None: self.standard = name self.holes = hs @property def hole_sizes(self) -> List[str]: return [i.attrs["Size"] for i in self.holes] def main(): app = qw.QApplication() mm = mw() mm.show() app.exec() exit() if __name__ == "__main__": ug_base_dir = os.getenv("UGII_BASE_DIR") if ug_base_dir is None or ug_base_dir == "": pass else: file_dir = os.path.join(ug_base_dir, "UGII", "modeling_standards") w_path = r_path = os.path.join(file_dir, "NX_Thread_Standard.xml") backup_path = os.path.join(file_dir, "NX_Thread_Standard_bak.xml") if not os.path.exists(r_path): raise FileNotFoundError(r_path) if not os.path.exists(backup_path): import shutil shutil.copy(r_path, backup_path) main() 没有写删除的功能,怕不小心误操作,要删除某一个规格的话,自己打开 相应的XML文件,手动删除行就行了

如何通过二次开发Python为UG添加特定螺纹规格?