
上个月接到一个挺折磨人的任务公司要做一批DN50到DN200、一共20种规格的法兰盘模型每种还要出STEP和PDF。如果靠手拖草图我估计要在SolidWorks里泡一整天更让人崩溃的是这种活儿不管做多少次都没有任何积累价值。第一反应是写VBA宏可写到一半我就放弃——调试太难受了变量没有类型提示想读个Excel参数表还得先启动Excel对象逻辑稍微绕一点就头晕。后来想起Python有PyWin32这个COM桥接库可以直接调用SolidWorks的API于是我把整个流程搬到了Python里。最终的效果是双击一下脚本20个法兰盘自动生成、自动保存、自动导出STEP总耗时不到两分钟。这篇博文就是这次实践的完整记录从环境搭建、COM调用思路、参数化建模脚本到我从VBA迁移过来时踩过的各种坑。适合两类人一是被SolidWorks重复建模折磨的工程师、结构设计师二是想给传统CAD流程加自动化脚本但从没找到切入点的Python新手。我不会把每个API参数都讲成说明书而是用“我要解决什么、为什么这么做、结果如何”的方式把整套思路讲清楚。1. 为什么我要抛弃VBA改用Python操作SolidWorks1.1 自动化需求背后的本质流程比单条命令值钱先说我最初面对的工作内容。手工建模一个法兰盘的流程大概是新建零件在前视基准面画外圆和内孔草图拉伸成主体再选择平面画螺栓孔草图圆周阵列倒角保存SLDPRT另存为STEP和PDF。如果只做一个模型手工画大概20分钟能搞定看起来没什么问题。但真实工程里的需求很少是“做一个”而是“做一批”。法兰盘有DN50、DN65、DN80、DN100……一直到DN200每种还有不同的压力等级导致外径、厚度、螺栓孔数量、螺栓孔分布圆直径全都不一样。手工做一个还能忍做20个就变成了机械劳动而且极其容易出错先画哪个孔、阵列角度是从0度还是15度开始、倒角大小抄错了表里的哪一个数全是潜在问题。所以我需要的不是“提高画一个模型的速度”而是“把建模流程本身变成可以反复执行的参数化流水线”。批量的规格参数放在一张表里脚本读表、生成模型、保存导出全程不回SolidWorks界面手动操作。这样的自动化才有意义。这也是为什么我一开始想用VBA因为SolidWorks内置宏录制按一下就能把操作录成代码。1.2 VBA宏调试与维护的慢性疼痛VBA写SolidWorks宏最直观的优点是没有环境成本宏编辑器就在SolidWorks里面录一段就能跑。但真把它当工程工具用问题很快就暴露出来。首先是调试体验。VBA编辑器虽然有F8单步、有变量监视但在一个几万行的工程里这种调试方式远远不够。尤其当你需要临时验证某个API返回什么值时要到处插MsgBox弹窗弹到怀疑人生。Python里我可以直接print对象属性和调用结果或者用pdb断点、VSCode调试器体验完全是另一个时代。其次是代码复用和版本管理。VBA宏文件本质上是嵌入在宏工程里的模块复制出来做diff、做git版本管理都很别扭。我实际遇到过好几次模型模板升级了宏也要跟着改但因为宏文件没有完善的版本历史根本不知道哪个宏对应哪一版模板。Python工程可以用git管理改动历史清清楚楚代码模块还可以抽出来给不同脚本共用。第三是生态几乎没有。VBA处理Excel参数表一个方案是创建Excel.Application对象逐单元格读取慢且繁琐另一个方案是直接Copy Paste但代码又脆又难看。Python这边用openpyxl或pandas读Excel只是几行代码的事处理JSON、日志、文件路径、正则表达式、发邮件全都有成熟库。做自动化流程的时候你往往不只是建模还要做数据准备、结果校验、通知分发VBA在这些环节几乎帮不上忙。1.3 PythonPyWin32的优势清单用PythonPyWin32替换VBA之后我的实际感受可以整理成一张表方便你判断自己是不是也适合迁移对比维度VBA宏Python PyWin32调试体验宏编辑器单步依赖MsgBoxVSCode断点、日志、print即时输出代码组织宏模块复用靠复制函数/类/模块git管理数据处理需要Excel对象或手工Copyopenpyxl/pandas直接读写几行代码错误日志Debug.Print不易留存logging模块落盘控制台可测试性基本没有可以用pytest做回归测试图形界面UserForm老旧tkinter/PySide轻松做参数界面跨软件组合很难Excel参数表→SolidWorks建模→导出→发邮件全串起来API智能提示无win32com动态分发可dir()查看或gencache生成类型库结论很简单如果只是偶尔录个宏VBA够用。但如果你要把建模自动化当做一个长期维护的工具、甚至分享给同事用Python这套组合的性价比明显更高。唯一需要补的知识是COM而这个恰恰是PyWin32的核心用武之地。2. 环境准备让Python和SolidWorks“握上手”2.1 版本对齐是第一步也是最容易翻车的一步PyWin32操作SolidWorks底层走的是Windows COM机制。SolidWorks本身是一个COM服务器外部程序通过COM接口调用它的API。这里有一个容易被忽略但极其关键的点SolidWorks是64位程序你的Python也必须是64位。我第一次没注意这个问题用的是一台机器上自带的32位Python结果win32com.client.Dispatch(SldWorks.Application)直接报错类似“没有注册类”。一开始以为是SolidWorks没装好折腾了半天最后才发现是Python位数不对。32位Python去调64位COM组件注册表路径都不一样当然找不到。换成64位Python之后一条报错都没再出现过。安装依赖很简单pip install pywin32 openpyxl验证是否装好在Python交互环境里跑一句import win32com.client import pythoncom import openpyxl print(pywin32 ok)如果没报错说明环境没问题。注意pythoncom是PyWin32的子模块它负责COM初始化和底层调用后面写代码会用到。2.2 连接SolidWorks的两种方式与选用原则连接SolidWorks最基本的一行代码是import win32com.client sw win32com.client.Dispatch(SldWorks.Application)这行代码的行为是如果SolidWorks已经在运行通常连接现有实例如果没运行就启动一个新的SolidWorks进程。实际操作中我更推荐先用DispatchEx它更适合明确指定连接一个新实例的场景。不过SolidWorks这个软件比较特殊同时开多个实例容易引发许可冲突和文件锁定所以我的习惯是先手动把SolidWorks打开再用脚本连接现有实例。这样既避免了脚本替你启动时的许可弹窗也能保证用户看到建模过程不会被误以为是死机。连接成功后要做两件事sw.Visible True model sw.ActiveDocsw.Visible控制SolidWorks主窗口是否显示。调试阶段建议设为True方便观察建模过程批量跑稳定了可以设False让它在后台干活。拿到model sw.ActiveDoc之后你就有了当前打开的文档对象。如果是新建零件用sw.NewPart()创建然后取ActiveDoc。2.3 从“模拟用户操作”理解SolidWorks的COM API这是整个自动化里最重要的一层认知。SolidWorks的API和很多现代软件的API不一样它的设计思路非常接近“模拟人在界面里的操作”先选择某个基准面然后插入草图画线画圆退出草图选择特征命令设置参数生成特征。所以用Python写SolidWorks自动化的时候你脑子里要有这样一张对象层级图SldWorks.Application应用对象 └── ModelDoc2文档对象零件/装配体/工程图 ├── SketchManager草图管理器 ├── FeatureManager特征管理器 ├── SelectionMgr选择管理器 └── Extension扩展功能选择、属性、另存等举一个最典型的操作序列在前视基准面上创建一个圆并拉伸。# 1. 清除选择 model.ClearSelection() # 2. 选中前视基准面 model.Extension.SelectByID2(Front Plane, PLANE, 0, 0, 0, False, 0, None, 0) # 3. 插入草图 model.SketchManager.InsertSketch(True) # 4. 画一个以原点为圆心、半径为10mm的圆 model.SketchManager.CreateCircleByRadius(0, 0, 0, 0.01) # 5. 退出草图 model.SketchManager.InsertSketch(True) # 6. 拉伸 model.FeatureManager.FeatureExtrusion2(...)这里每一步都像是在代替用户点一次按钮。理解这一点之后遇到不熟悉的API就不会慌你可以先打开录制宏手动操作一遍再看录制结果照着流程搬成Python。2.4 API怎么查最省时间SolidWorks的API文档主要以VBA和C#示例为主Python资料很少。但好消息是COM接口是语言无关的VBA里怎么调用Python里就怎么调用只是语法不同。最省时间的路子是先录制VBA宏再把宏翻译成Python。比如你想实现“修改一个尺寸”录制宏之后会得到类似Part.Parameter(D1草图1).SystemValue 0.02的代码翻译成Python就是一模一样的调用。这个方法能解决80%的“不知道怎么调API”的问题。另外SolidWorks安装目录下通常有完整的API Help搜索方法名能看到参数签名、返回值、版本兼容说明。遇到某个方法报参数数量不对第一反应不是瞎试而是打开API Help按版本确认签名。3. 参数化建模实例法兰盘批量生成器完整代码3.1 需求与程序设计我把这次需求设计成一个可以直接改参数就跑的脚本Excel表格里维护法兰规格脚本读表之后在SolidWorks里逐个建零件、保存、导出STEP。程序的整体流程如下读取Excel参数表包含名称、外径、内径、厚度、螺栓孔数量、螺栓孔分布圆直径。连接SolidWorks。遍历每一行参数新建零件用草图拉伸生成法兰主体保存为SLDPRT导出STEP打印日志与耗时。Excel参数表长这样名称外径mm内径mm厚度mm螺栓孔数螺栓孔分布圆mm螺栓孔径mmDN501656118412518DN802007720816018DN10022092208180183.2 完整代码下面的代码我做了简化处理保留了最核心的可运行结构。需要注意FeatureExtrusion2等建模相关API在不同SolidWorks版本里的参数签名不完全一样运行前建议先用录制宏功能录一次拉伸操作把录制结果里的参数搬过来替换。这个不是偷懒而是版本兼容性带来的现实问题后面第6章还会细说。import os import time import win32com.client import pythoncom from openpyxl import load_workbook # ---- 常用SolidWorks枚举常量后期绑定方式 ---- swDocPART 1 # 零件文档类型 swOpenDocOptions_Silent 1 # 静默打开 swSaveAsOptions_Silent 1 # 静默保存 swSaveAsCurrentVersion 0 # 保存为当前版本 swCustomPropertyType_Text 30 # 自定义属性文本类型 SW_MM_TO_M 0.001 # 毫米 - 米 def connect_solidworks(): 连接SolidWorks。如果已启动则直接连接否则启动新实例。 sw win32com.client.DispatchEx(SldWorks.Application) sw.Visible True return sw def mm(value_mm): SolidWorks API里长度单位是米这里统一转换。 return value_mm * SW_MM_TO_M def set_custom_property(model, name, value): 给模型设置自定义属性例如物料编码、图号等。 prop_mgr model.Extension.CustomPropertyManager() # Add3参数(属性名, 类型枚举, 值, 是否覆盖已有属性) # 老版本可能没有Add3可改用Add或Add2 prop_mgr.Add3(name, swCustomPropertyType_Text, str(value), True) def create_flange(sw, outer_d, inner_d, thick, hole_count, bolt_circle_d, hole_d): 创建法兰盘的主体简化版 1. 新建零件 2. 在前视基准面画外圆和内孔草图 3. 拉伸生成环形主体 真实项目中还要继续创建螺栓孔并进行圆周阵列这里用注释标记了API位置。 sw.NewPart() model sw.ActiveDoc sk_mgr model.SketchManager feat_mgr model.FeatureManager # 选中前视基准面进入草图 model.ClearSelection() model.Extension.SelectByID2(Front Plane, PLANE, 0, 0, 0, False, 0, None, 0) sk_mgr.InsertSketch(True) # 画外圆和内孔圆注意坐标和半径单位都是米 sk_mgr.CreateCircleByRadius(0, 0, 0, mm(outer_d) / 2.0) sk_mgr.CreateCircleByRadius(0, 0, 0, mm(inner_d) / 2.0) # 退出草图 sk_mgr.InsertSketch(True) # 拉伸生成法兰主体 # 这个API的参数在不同版本有差异运行前务必用录制宏校准 feat_mgr.FeatureExtrusion2( True, False, False, 0, 0, mm(thick), 0, False, False, False, False, 0, 0, False, False, False, False, True, True, True, 0, 0, False ) # 到这里法兰盘环形主体已经生成。 # 螺栓孔的创建思路是选一个平面画小圆然后使用圆周阵列特征。 # 因为不同版本的阵列API签名差异较大这里不贴完整实现。 # 建议你录制一次“画孔圆周阵列”的宏再翻译成Python。 # 写入自定义属性方便后续在BOM中识别 set_custom_property(model, 名称, 法兰盘) set_custom_property(model, 规格, fDN{int(inner_d)}) return model def export_step(model, step_path): 将当前模型导出为STEP文件。 # SaveAs的第一个参数是完整路径第二个参数用SaveAsCurrentVersion # 第三个参数需要传导出选项。实际使用时可结合API帮助调整。 status model.Extension.SaveAs( step_path, swSaveAsCurrentVersion, swSaveAsOptions_Silent, None, , True ) return status def main(excel_path, output_dir): if not os.path.exists(excel_path): print(f参数表不存在{excel_path}) return os.makedirs(output_dir, exist_okTrue) wb load_workbook(excel_path, data_onlyTrue) ws wb.active sw connect_solidworks() total_start time.time() for row in ws.iter_rows(min_row2, values_onlyTrue): name, outer_d, inner_d, thick, hole_count, bolt_circle_d, hole_d row[:7] if not name: continue print(f正在生成{name} (外径{outer_d} 内径{inner_d} 厚{thick})) start time.time() model create_flange( sw, outer_d, inner_d, thick, int(hole_count), bolt_circle_d, hole_d ) part_path os.path.join(output_dir, f{name}.SLDPRT) model.SaveAs3(part_path, 0, swSaveAsOptions_Silent, None, , True) step_path os.path.join(output_dir, f{name}.STEP) try: export_step(model, step_path) except Exception as e: print(f 导出STEP失败{e}) elapsed time.time() - start print(f 完成 {name}耗时 {elapsed:.1f}s) total_elapsed time.time() - total_start print(f全部完成总耗时 {total_elapsed:.1f}s) if __name__ __main__: main(flange_params.xlsx, output_flanges)这段代码里我故意做了两个简化一是没有把圆周阵列做全二是把模型主体限定为拉伸生成的环形。原因是阵列相关API在不同版本里参数差异很大贴一版“看似精确但实际跑不通”的代码反而害人。真实项目中你需要用录制宏把“画螺栓孔圆周阵列”这段录下来再把录制结果翻译成Python照搬到代码注释标记的位置。3.3 代码执行效果与日志脚本正常运行后控制台输出大致是这样正在生成DN50 (外径165 内径61 厚18) 完成 DN50耗时 3.2s 正在生成DN80 (外径200 内径77 厚20) 完成 DN80耗时 2.8s ... 全部完成总耗时 52.4s20个规格全部跑完不到一分钟。相比手工一个个建模效率提升了不止一个量级。关键是下次参数改了一张表重新跑一遍就行整个过程不需要打开SolidWorks做任何手动操作。3.4 更稳妥的企业级方案模板零件 改尺寸如果你在工程单位里做自动化有一个比“从零建模”更稳的方案先建好一个模板零件保留所有特征但把关键尺寸做成可修改的然后脚本打开模板、挨个修改尺寸、另存为新零件。这个方案的好处是不用碰FeatureExtrusion2这种参数复杂、版本敏感的建模API只需要调用Parameter(D1草图1).SystemValue 0.02这类简单的尺寸修改API稳定性高得多。对于法兰、齿轮、型材这类“结构不变、尺寸变化”的零件这是企业里最推荐的自动化模式。# 打开模板 err win32com.client.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0) warn win32com.client.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0) model sw.OpenDoc6(法兰模板.SLDPRT, swDocPART, swOpenDocOptions_Silent, , err, warn) # 修改关键尺寸 model.Parameter(D1草图1).SystemValue mm(outer_d) / 2.0 model.Parameter(D2草图1).SystemValue mm(inner_d) / 2.0 # 另存为新零件 model.SaveAs3(DN50.SLDPRT, 0, swSaveAsOptions_Silent, None, , True)这种方式我强烈推荐尤其是要交付给其他同事使用的时候。它比“每次用代码重建所有特征”更容易排查问题也更容易让不懂Python的人理解。4. VBA到Python的迁移对照语法、习惯与思维变化4.1 代码写法对比表如果你已经会VBA迁移到Python最大的障碍不是API而是写代码的“姿势”。我把常见对照整理成了一张表场景VBA写法Python PyWin32写法获取SolidWorks对象Set swApp CreateObject(SldWorks.Application)sw win32com.client.Dispatch(SldWorks.Application)新建零件Set Part swApp.NewPartsw.NewPart()model sw.ActiveDoc选择基准面Part.Extension.SelectByID2 Front Plane, PLANE, 0,0,0, False, 0, None, 0model.Extension.SelectByID2(..., False, 0, None, 0)画圆Part.SketchManager.CreateCircleByRadius 0,0,0, 0.01model.SketchManager.CreateCircleByRadius(0,0,0, 0.01)弹窗提示MsgBox 完成print(完成) logging获取枚举常量通过引用类型库直接可用Dispatch后期绑定常量为空需要自定义常量错误处理On Error Resume Nexttry / except pywintypes.com_error延时等待DoEventstime.sleep(0.5)数组Dim arr(1 To 10) As Doublearr [0.0] * 10表格不是重点真正的重点是下面几个思维转变。4.2 Python中调用SolidWorks枚举常量的两种方式VBA里因为引用了SolidWorks的类型库所有枚举常量比如swDocPART、swSaveAsCurrentVersion直接就能用。但Python用Dispatch做后期绑定时拿不到类型库的常量列表。这时候有两个选择。选择一用win32com.client.gencache.EnsureDispatch提前生成并缓存类型库之后可以通过win32com.client.constants.swDocPART访问常量。这个方法能拿到类型库信息第一次运行会慢一些而且某些SolidWorks版本和Python版本的组合下类型库缓存会和COM实现有兼容问题反而增加排错成本。选择二继续用Dispatch做后期绑定自己把用到的枚举常量定义成Python变量。我个人推荐第二种。因为SolidWorks脚本里真正用到的常量数量其实不多十几个足够自己写成一个常量模块反而更透明、更好维护。# constants_solidworks.py swDocPART 1 swDocASSEMBLY 2 swDocDRAWING 3 swOpenDocOptions_Silent 1 swSaveAsOptions_Silent 1 swSaveAsCurrentVersion 0 swCustomPropertyType_Text 304.3 VBA里的“模块/类”变成Python的“函数/类”VBA宏最常见的形式是一大段线性代码从获取对象开始一路操作到保存。这种写法在Python里当然也能跑但跑不了几次你就会发现建带孔法兰板的代码和建底座板的代码有大量重复复制粘贴两份之后一旦API参数要改就得改两处。我在第一次迁移时就把代码拆成了几个函数connect_solidworks()负责连接、create_base_plate()负责建底板、create_holes()负责打孔、export_step()负责导出。这样每次接到新需求就是组合几个函数而不是从头写。另外VBA常用的全局变量思维也要改。Python里尽量通过参数传递数据少用全局变量。这样脚本可以做成类把SolidWorks连接对象、输出目录、日志器都在__init__里初始化逻辑更清晰。4.4 事件处理和命令等待VBA和SolidWorks协同工作时经常用DoEvents来让界面响应。Python的COM调用是同步阻塞的OpenDoc6没执行完下一行代码不会跑所以大部分场景不需要手动等待。但有一个场景需要注意导出STEP或PDF时文件写入是异步落盘的脚本往下走可能文件还没写完。我一般在导出后加一个time.sleep(0.5)或者轮询文件大小不为0再加个短暂等待。不要过度依赖固定时间环境繁忙时候会不够最好用“检查文件是否存在且大小超过1KB”作为完成标志。def wait_for_file(path, timeout30): start time.time() while time.time() - start timeout: if os.path.exists(path) and os.path.getsize(path) 1024: return True time.sleep(0.5) return False5. 自动化落地实战从单一零件到批量导出与管理5.1 批量导出STEP/PDF模型建好后批量导出的需求立刻就会出现。一个简单的批量导出脚本框架如下import os import time import win32com.client import pythoncom swDocPART 1 swOpenDocOptions_Silent 1 swSaveAsOptions_Silent 1 swSaveAsCurrentVersion 0 def open_model(sw, file_path): 打开SolidWorks零件返回模型对象。err/warn必须用按引用方式传递。 err win32com.client.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0) warn win32com.client.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0) model sw.OpenDoc6(file_path, swDocPART, swOpenDocOptions_Silent, , err, warn) return model def export_pdf(model, pdf_path): 导出PDF用的方式是保存一份当前文档副本。 return model.SaveAs(pdf_path, 0, 0, None, , True) def export_step(model, step_path): 导出STEP沿用Extension的SaveAs方法。 return model.Extension.SaveAs( step_path, swSaveAsCurrentVersion, swSaveAsOptions_Silent, None, , True ) def batch_export(sldprt_dir, out_dir): sw win32com.client.Dispatch(SldWorks.Application) sw.Visible False os.makedirs(out_dir, exist_okTrue) for file_name in os.listdir(sldprt_dir): if not file_name.lower().endswith(.sldprt): continue base_name os.path.splitext(file_name)[0] full_path os.path.join(sldprt_dir, file_name) model open_model(sw, full_path) export_pdf(model, os.path.join(out_dir, base_name .PDF)) export_step(model, os.path.join(out_dir, base_name .STEP)) print(f已导出{base_name}) print(批量导出完成) if __name__ __main__: batch_export(rD:\models, rD:\exports)注意OpenDoc6的几个非常规参数。SolidWorks的API要求传入error和warning两个整型变量用于返回打开文档时的错误和警告。在Python里这两个参数必须包装成VARIANT按引用传否则会报参数类型不匹配。这属于PyWin32和SolidWorks API结合时的经典坑。5.2 批量设置自定义属性批量建模还有一个高频需求给一堆模型写入“物料编码”“材料”“审核”等自定义属性。SolidWorks的属性工具按钮在界面上点起来很慢几十个零件一个个填属性也是纯粹的体力活。用Python做就很简单def set_property(model, prop_name, value): prop_mgr model.Extension.CustomPropertyManager() prop_mgr.Add3(prop_name, swCustomPropertyType_Text, str(value), True)注意Add3在不同版本里的行为略有差异老版本可能只有Add2。如果你在跑的时候报“方法不存在”把Add3换成Add2或Add。另一个常见问题是属性写入之后如果模型处于只读状态或打包打开会写不进去。所以脚本里最好先检查文档读写状态。5.3 把自动化嵌入日常工作流脚本写出来只是第一步让它真正改善工作流还需要考虑使用体验。我目前是这样组织的Excel参数表放在一个固定目录双击运行一个run_flange_gen.bat批处理里面只有一行python flange_gen.py。脚本运行过程中把日志同时输出到控制台和logs/目录这样即使跑完关掉窗口也能回头查看哪一步出错。如果要把脚本给不会配Python环境的同事用可以用PyInstaller打包pip install pyinstaller pyinstaller -F -w flange_gen.py打包出来的exe可以直接双击运行只要目标机器装了SolidWorks就行。不过要注意杀毒软件可能会有误报打包时加--version-file和签名能减少误报概率但那是另一个话题了。5.4 与设计BOM对接做到这一步自动化就已经不只是“建模自动化”而是“产品数据自动化”了。Excel里的BOM表一旦维护好脚本可以读BOM里的每一个零件规格自动生成模型、自动导出、自动改名甚至把结果物料编码写回Excel。我用这套思路做完法兰盘之后逐渐把齿轮、轴承座、电机安装板都做成了类似的参数化生成器。每新增一类零件不是新写一套脚本而是复用已有的连接、导出、日志、BOM读取模块只改中间的建模函数。这也再次印证了第4章的观点把自动化当做一个软件工程来做而不是写一次性宏后期收益会非常大。6. 踩过的坑与性能提升技巧6.1 32位Python与64位SolidWorks的经典冲突这是第一个坑也是环境问题里最隐蔽的。整台机器上如果有多个Python解释器命令行里敲python得到的不一定是64位版本。用platform.architecture()自查一下import platform print(platform.architecture())如果显示(32bit, WindowsPE)解释器就是32位的建议重新安装64位Python或者用py -3 -m pip install pywin32这类方式明确指定。这个坑的典型报错是pywintypes.com_error: (-2147221164, 没有注册类, None, None)看到这个错误第一件事不是翻SolidWorks设置而是检查Python位数。6.2 COM对象不释放导致SolidWorks进程残留用PyWin32操作SolidWorks脚本结束时不释放COM引用会让SolidWorks进程一直留在后台。如果只是残留一两个还好反复调试几次内存越占越多最后电脑卡到不动。我的处理方式是脚本主逻辑外面套一层try/finally在finally里把所有对象引用置空并调用pythoncom.CoUninitialize()sw None model None pythoncom.CoUninitialize()注意pythoncom.CoUninitialize()要在所有COM操作结束之后调用。如果你不需要完全退出SolidWorks进程就不要随便调sw.ExitApp()否则会把你后台可能正在打开的其他模型也连带关闭。我的习惯是建模类脚本结束后让它保持运行状态用户可以直接查看结果只是批量导出类脚本结束后主动sw.ExitApp()退出SolidWorks避免后台挂着无界面的进程。6.3 SelectByID2的隐藏依赖SelectByID2看着简单实际坑不少。它的第三个、第四个、第五个参数是坐标单位是米。很多人在零件模式下想选一个草图平面随便传了(0, 0, 0)进去结果选不中——因为该特征的实际位置可能不在原点附近。更常见的做法是传(0, 0, 0)并依赖名称选中基准面比如Front Plane这时坐标参数往往可以传0。但如果你要选的是一个偏移平面最好从特征树里获取特征名称后再选择。另外SelectByID2对视图有依赖某些情况下对象不可见就选不中。碰到这种先把视图切到最合适的方向或者用model.ShowNamedView2(*Front, 7)这种命令刷新一下再选。调试时如果发现“看似代码没问题但选择失败”大概率就是视图或坐标问题。6.4 单位制混乱SolidWorks API里的长度单位默认是米但国内很多图纸习惯用毫米。直接写数字会导致模型尺寸差1000倍生成一个巨大或微小的零件。我的做法是统一封装一个mm()函数所有从Excel读进来的毫米数值进入API前都经过它转换def mm(value): return value * 0.001别嫌这一步啰嗦它省掉的不仅是来回换算还有排查“模型怎么变成无穷大”的时间。6.5 性能优化减少重绘与重建批量建模时最影响速度的不是建模计算本身而是视口重绘和每步操作后的界面刷新。早期版本我在每个特征生成后都调用sw.ViewZoomtofit2去合适的视图结果跑20个模型要多花好几分钟。优化思路很简单批量操作时不做视图操作全部生成完再一次刷新。界面刷新不是必须的脚本本来就不需要“看”模型。当然这也意味着你在调试时不容易看到中途效果所以我建议调试阶段开Visible批量跑的阶段关掉。另一个细节是设置用户偏好关掉那些会弹出输入框的选项。比如尺寸输入框如果用API创建特征时还弹出“请输入尺寸”脚本就会卡住。用sw.SetUserPreferenceToggle关闭相关选项跑完再恢复。# 关闭尺寸输入弹窗具体枚举值见API Help sw.SetUserPreferenceToggle(10, False) # 举例请按版本调整这个枚举值不同版本不一样不要照抄去API Help里搜“SetUserPreferenceToggle”确认。6.6 版本不同API签名漂移最后是最现实的一个问题SolidWorks每个大版本都会改API尤其像FeatureExtrusion、阵列这类复杂方法参数数量和含义经常变化。同一段Python代码在SolidWorks 2020上能跑换成2023可能就报“参数数量错误”。我的应对策略是建立一个“版本校准”的习惯。接到新环境后先录一段VBA宏把关键操作录下来然后对照宏里的API调用改好Python代码里的参数跑通后再开始批量。这套流程不复杂但能省掉大量浪费时间。我也不追求“一套代码通吃所有版本”因为在工程环境里版本升级通常伴随着迁移窗口代码跟着版本走是正常的。把版本信息写在脚本开头的注释里以后换机器、换版本时一眼就能看出该改哪里。我自己的习惯是接到这类自动化任务先不急着写代码先把流程录一遍VBA宏、把参数表整理好再用Python把流程串成脚本。模型生成完不要全流程自动化跑完就跑至少随机打开两三个检查特征树和尺寸自动化不是免检的。踩过这么多坑之后我依然觉得这套方案值得它把“手工建模2小时”压到了“跑脚本2分钟”而且下次要调参数改Excel就行不用再进SolidWorks里慢慢画。最后提醒一句PyWin32只是桥真正核心的是你要有“把流程拆成参数和命令”的能力。多练几次你会发现不只是SolidWorks其他Windows软件也可以按这套思路自动化。