Python驱动CAD自动化:从零构建你的第一个几何批处理脚本
1. 为什么需要Python驱动CAD自动化我见过太多工程师重复点击CAD界面到手指发麻的场景。上周还有个做市政规划的朋友吐槽他每天要手动统计上百张图纸里绿化带的面积数据这种机械操作既容易出错又消耗创造力。其实用Python写个脚本就能搞定——比如自动识别所有闭合多段线计算面积后导出Excel报表整个过程从8小时压缩到3分钟。CAD软件的API接口就像藏在菜单深处的瑞士军刀而Python就是打开它的万能钥匙。通过pyautocad或comtypes这样的库我们可以直接操控CAD对象模型。比如这段代码就能获取当前图纸里所有圆形的半径import pyautocad acad pyautocad.Autocad() for obj in acad.iter_objects(Circle): print(f圆心在({obj.Center[0]}, {obj.Center[1]})半径{obj.Radius})2. 环境搭建5分钟快速配置2.1 安装必备工具链首先确保你的电脑有AutoCAD2015以上版本和Python 3.7。我实测过在Win10AutoCAD 2023Python 3.10的组合最稳定。通过pip安装关键库pip install pyautocad comtypes openpyxl注意如果遇到权限错误可以加上--user参数。安装完成后建议重启CAD否则可能遇到接口未注册的错误。2.2 测试连接CAD新建一个test_connection.py文件写入以下代码from pyautocad import Autocad acad Autocad(create_if_not_existsTrue) print(f当前激活文档{acad.doc.Name}) acad.prompt(Hello, AutoCAD!\\n)运行后你会看到CAD界面弹出命令行提示这说明桥梁已经搭好了。如果报错检查CAD是否以管理员权限运行。3. 实战批量提取多段线坐标3.1 理解CAD对象模型CAD中的每个图形都是对象它们像俄罗斯套娃一样有层级关系。比如一个多段线Polyline对象包含Coordinates属性所有顶点的(x,y,z)坐标元组Layer属性所在图层名称Closed属性是否闭合通过这个结构我们可以像查数据库一样筛选对象。比如要找出道路图层所有闭合多段线roads [ obj for obj in acad.iter_objects(Polyline) if obj.Layer 道路 and obj.Closed ]3.2 构建完整批处理脚本下面这个脚本实现了遍历当前图纸所有多段线筛选指定图层对象导出顶点坐标到CSVimport csv from pyautocad import Autocad def export_polyline_coords(output_file, target_layer): acad Autocad() with open(output_file, w, newline) as f: writer csv.writer(f) writer.writerow([ID, X, Y, Z]) for i, obj in enumerate(acad.iter_objects(Polyline)): if obj.Layer target_layer: points obj.Coordinates for j in range(0, len(points), 3): writer.writerow([ i, points[j], points[j1], points[j2] ]) export_polyline_coords(road_coords.csv, 道路)4. 进阶技巧处理复杂图形4.1 块参照(BlockReference)的破解之道CAD中的块就像编程里的函数可以重复调用。要提取块内实体需要递归遍历def explode_block(block_ref): entities [] for entity in block_ref.Explode(): if entity.EntityName AcDbBlockReference: entities explode_block(entity) else: entities.append(entity) return entities4.2 性能优化加速大批量处理当处理上万图形时可以用多线程缓存策略。这里有个实测有效的方案from concurrent.futures import ThreadPoolExecutor def process_objects_chunk(chunk): # 每个线程创建独立CAD连接 acad Autocad(create_if_not_existsTrue) return [obj.Handle for obj in chunk if obj.Layer 目标层] def fast_batch_process(): all_objects list(acad.iter_objects()) chunk_size len(all_objects) // 4 with ThreadPoolExecutor(max_workers4) as executor: results list(executor.map( process_objects_chunk, [all_objects[i:ichunk_size] for i in range(0, len(all_objects), chunk_size)] )) return [handle for sublist in results for handle in sublist]5. 错误处理与调试心得CAD自动化脚本最常遇到三类问题对象失效图形被删除但句柄还在类型转换错误CAD返回的COM对象需要特殊处理权限问题CAD主线程被阻塞这里分享几个实用调试技巧在关键操作前后添加acad.prompt()打印状态用try-except包裹危险操作时捕获pyautocad.types.COMError对于图形闪烁问题可以临时关闭重绘acad.doc.SetVariable(BACKGROUNDPLOT, 0) # 关闭后台打印 acad.doc.SetVariable(CMDECHO, 0) # 关闭命令回显 # 执行密集操作... acad.doc.Regen(0) # 最后统一重绘记得有次我写的脚本突然卡死后来发现是忘了释放COM对象。现在养成了在finally块调用pythoncom.CoUninitialize()的习惯。