Python自动化SolidWorks批量转换SLDPRT到STL教程(基于SW软件接口实现)

Python自动化SolidWorks批量转换SLDPRT到STL教程(基于SW软件接口实现)

admin
4月15日发布
温馨提示:
本文最后更新于2025年04月15日,已超过197天没有更新,若内容或图片失效,请留言反馈。

本文详解如何通过Python调用SolidWorks API实现SLDPRT文件批量转STL格式,提供完整代码解析与多版本兼容方案。学习自动化3D模型转换技巧,提升预处理效率,适用于机械工程师与开发者快速处理大批量CAD文件转换需求。

遇到的问题

在3D打印、跨平台协作、模型归档等场景中,将SolidWorks的SLDPRT零件文件转换为通用STL格式是常见需求。传统手动转换方式存在明显痛点:

  • 耗时费力:单个文件需经历"打开-导出-关闭"重复操作
  • 版本兼容:不同SolidWorks版本间转换易出错
  • 批量处理:缺乏自动化导致大规模文件处理效率低下

环境准备

首先,需要安装了SolidWorks,例如小栈是安装了SolidWorks2024版本。

m9i6171f.png

然后新建个Python环境,第三方库只需要安装个pywin32:

pip install pywin32  # 必需依赖

Python源码

直接上源码,话不多说:

import os
import sys
import traceback
import time
import json
import platform
from pathlib import Path

# 检查必要依赖并提供友好提示
try:
    import win32com.client
    import win32api
except ImportError:
    print("错误: 缺少必要的依赖库。")
    print("请安装以下库: pywin32")
    print("安装命令: pip install pywin32")
    sys.exit(1)

# 配置文件路径 - 使用pathlib提高跨平台兼容性
CONFIG_FILE = Path(__file__).parent / "sw_config.json"

# 显示程序信息和环境
script_path = Path(__file__).absolute()
script_name = script_path.name
script_name_without_ext = script_path.stem
last_modified_time = time.strftime("%H:%M:%S", time.localtime(os.path.getmtime(script_path)))

print(f"我是{script_name_without_ext},最后一次编辑时间为:{last_modified_time}")
print(f"运行环境: Python {platform.python_version()} on {platform.system()} {platform.release()}")


# 加载配置函数
def load_config():
    if CONFIG_FILE.exists():
        try:
            with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
                config = json.load(f)
            print(f"已加载上次配置")
            return config
        except Exception as e:
            print(f"加载配置文件失败: {str(e)}")
    return {"input_directory": "", "output_directory": ""}


# 保存配置函数
def save_config(input_dir, output_dir):
    try:
        config = {
            "input_directory": input_dir,
            "output_directory": output_dir
        }
        with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
            json.dump(config, f, ensure_ascii=False, indent=4)
        print("已保存当前配置")
    except Exception as e:
        print(f"保存配置失败: {str(e)}")


def convert_sldprt_to_stl(input_directory, output_directory):
    swApp = None
    try:
        # 多级尝试连接SolidWorks
        connection_methods = [
            # 方法1: 连接到现有实例
            lambda: (win32com.client.GetActiveObject("SldWorks.Application"), "已连接到正在运行的SolidWorks实例"),
            # 方法2: 尝试创建指定版本(按新到旧顺序)
            lambda: (win32com.client.Dispatch("SldWorks.Application.31"), "已创建新的SolidWorks实例 (版本31)"),
            lambda: (win32com.client.Dispatch("SldWorks.Application.30"), "已创建新的SolidWorks实例 (版本30)"),
            lambda: (win32com.client.Dispatch("SldWorks.Application.29"), "已创建新的SolidWorks实例 (版本29)"),
            lambda: (win32com.client.Dispatch("SldWorks.Application.28"), "已创建新的SolidWorks实例 (版本28)"),
            lambda: (win32com.client.Dispatch("SldWorks.Application.27"), "已创建新的SolidWorks实例 (版本27)"),
            lambda: (win32com.client.Dispatch("SldWorks.Application.26"), "已创建新的SolidWorks实例 (版本26)"),
            # 方法3: 尝试创建默认版本
            lambda: (win32com.client.Dispatch("SldWorks.Application"), "已创建新的SolidWorks实例 (默认版本)")
        ]

        # 依次尝试各种连接方法
        for method in connection_methods:
            try:
                swApp, message = method()
                print(message)
                break
            except Exception:
                continue

        if swApp is None:
            print("无法连接到SolidWorks实例,请确保SolidWorks已正确安装。")
            return

        # 显示SolidWorks窗口
        swApp.Visible = True

        # 验证 SolidWorks 版本
        try:
            version_info = swApp.RevisionNumber
            print(f"SolidWorks版本: {version_info}")
        except:
            print("无法获取SolidWorks版本信息,但将继续尝试转换")

        # 使用Path对象处理路径,提高跨平台兼容性
        input_path = Path(input_directory)
        output_path = Path(output_directory)

        # 筛选有效的SLDPRT文件
        valid_files = []
        try:
            # 使用列表推导式更高效地筛选文件
            upper_files = [file for file in input_path.glob("*.SLDPRT")
                           if not file.name.startswith("~$") and ".zip" not in file.name.lower()]
            lower_files = [file for file in input_path.glob("*.sldprt")
                           if not file.name.startswith("~$") and ".zip" not in file.name.lower()]

            # 合并并去重
            valid_files = list(set(upper_files + lower_files))
        except Exception as e:
            print(f"扫描目录时出错: {str(e)}")
            traceback.print_exc()
            return

        if not valid_files:
            print(f"在目录 {input_directory} 中未找到有效的SLDPRT文件")
            return

        print(f"找到 {len(valid_files)} 个SLDPRT文件需要转换")
        total_files = len(valid_files)
        success_count = 0
        fail_count = 0
        start_time = time.time()

        for index, file_path in enumerate(valid_files, 1):
            # 计算进度和预计剩余时间
            try:
                percent_complete = (index - 1) / total_files * 100
                elapsed_time = time.time() - start_time
                if index > 1:
                    avg_time_per_file = elapsed_time / (index - 1)
                    est_time_remaining = avg_time_per_file * (total_files - (index - 1))
                    time_str = f"- 已用时: {elapsed_time:.1f}秒, 预计剩余: {est_time_remaining:.1f}秒"
                else:
                    time_str = ""
            except Exception as e:
                print(f"警告: 计算进度时出错: {str(e)}")
                time_str = ""

            file_name = file_path.name
            print(f"[{index}/{total_files} - {percent_complete:.1f}%] 处理文件: {file_name} {time_str}")

            # 转换处理开始
            try:
                # 这里使用WinAPI获取短路径(若失败则使用原始路径)
                try:
                    short_path = win32api.GetShortPathName(str(file_path))
                except Exception as e:
                    short_path = str(file_path)
                    print(f"注意: 无法获取短路径,使用原始路径。错误: {str(e)}")

                if not os.path.exists(short_path):
                    print(f"路径无效或文件不存在: {short_path}")
                    fail_count += 1
                    continue

                # 尝试关闭所有打开文档
                try:
                    swApp.CloseAllDocuments(True)
                except Exception as e:
                    print(f"警告: 无法关闭已打开的文档。错误: {str(e)}")

                # 定义SolidWorks常量: swDocPART = 1
                swDocPART = 1

                # 尝试打开文档
                try:
                    # 方法1: 使用OpenDoc(更简单的接口)
                    model_doc = swApp.OpenDoc(short_path, swDocPART)
                    if model_doc is None:
                        try:
                            # 方法2: 使用不同参数组合的OpenDoc6
                            model_doc = swApp.OpenDoc6(short_path, swDocPART, 1, "", 0, 0)
                        except:
                            try:
                                # 方法3: 最简化参数的OpenDoc6
                                model_doc = swApp.OpenDoc6(short_path, swDocPART, 0, "", "", "")
                            except:
                                model_doc = None

                    if model_doc is None:
                        print(f"无法打开文件: {file_path}")
                        fail_count += 1
                        continue
                except Exception as e:
                    print(f"尝试打开文件失败: {str(e)}")
                    fail_count += 1
                    continue

                # 定义输出STL文件路径
                stl_file_path = output_path / f"{file_path.stem}.STL"

                # 使用 SaveAs 方法进行导出
                ret = model_doc.SaveAs(str(stl_file_path))
                if ret:
                    success_count += 1
                    print(f"文件已成功转换为STL: {stl_file_path}")
                else:
                    fail_count += 1
                    print(f"文件转换失败: {file_path}")
            except Exception as e:
                print(f"处理文件 {file_name} 时出错: {str(e)}")
                traceback.print_exc()
                fail_count += 1
            finally:
                # 尝试关闭当前文档
                try:
                    swApp.CloseDoc(file_name)
                    print(f"已关闭文档: {file_name}")
                except Exception as e:
                    print(f"关闭文档时出错: {str(e)}")

        print(f"批量转换完成! 成功: {success_count}, 失败: {fail_count}, 总计: {total_files}")

    except Exception as e:
        print(f"程序执行出错: {str(e)}")
        traceback.print_exc()
    finally:
        # 确保释放SolidWorks资源
        if swApp:
            try:
                swApp.ExitApp()  # 退出SolidWorks应用
                swApp = None
            except Exception as e:
                print(f"退出SolidWorks时出错: {str(e)}")


if __name__ == "__main__":
    try:
        # 加载上次的配置
        config = load_config()
        last_input_dir = config["input_directory"]
        last_output_dir = config["output_directory"]

        # 先获取输入文件夹路径
        if len(sys.argv) > 1:
            input_directory = sys.argv[1]
        else:
            # 显示上次的路径作为默认选项
            default_prompt = f" [按Enter使用默认值: {last_input_dir}]" if last_input_dir else ""
            input_prompt = f"请输入SLDPRT文件所在的文件夹路径{default_prompt}: "
            input_directory = input(input_prompt) or last_input_dir

        # 确认输入路径
        confirm_prompt = f"输入的SLDPRT文件所在目录是: {input_directory},确认吗? (y/n) [默认y]: "
        confirm = input(confirm_prompt) or 'y'
        while confirm.lower() != 'y':
            default_prompt = f" [按Enter使用默认值: {last_input_dir}]" if last_input_dir else ""
            input_directory = input(f"请输入SLDPRT文件所在的文件夹路径{default_prompt}: ") or last_input_dir
            confirm = input(f"输入目录是: {input_directory},确认吗? (y/n) [默认y]: ") or 'y'

        # 验证输入目录是否存在
        if not os.path.exists(input_directory):
            print(f"错误: 路径 {input_directory} 不存在!")
            sys.exit(1)

        # 让用户输入STL文件输出目录
        default_prompt = f" [按Enter使用默认值: {last_output_dir}]" if last_output_dir else ""
        output_directory = input(f"请输入STL文件输出的目录路径{default_prompt}: ") or last_output_dir
        confirm_out = input(f"输出目录是: {output_directory},确认吗? (y/n) [默认y]: ") or 'y'
        while confirm_out.lower() != 'y':
            default_prompt = f" [按Enter使用默认值: {last_output_dir}]" if last_output_dir else ""
            output_directory = input(f"请输入STL文件输出的目录路径{default_prompt}: ") or last_output_dir
            confirm_out = input(f"输出目录是: {output_directory},确认吗? (y/n) [默认y]: ") or 'y'

        # 验证输出目录是否存在,不存在则尝试创建
        if not os.path.exists(output_directory):
            try:
                os.makedirs(output_directory)
                print(f"输出目录 {output_directory} 已创建")
            except Exception as e:
                print(f"无法创建输出目录: {output_directory},错误: {str(e)}")
                sys.exit(1)

        # 保存当前配置
        save_config(input_directory, output_directory)

        # 开始转换工作(先筛选有效文件,再转换)
        convert_sldprt_to_stl(input_directory, output_directory)

    except KeyboardInterrupt:
        print("\n程序被用户中断")
    except Exception as e:
        print(f"发生错误: {str(e)}")
        traceback.print_exc()

    input("按Enter键退出...")

本方案基于Python的win32com模块实现SolidWorks自动化控制,核心优势包括:

  1. 智能版本适配:支持从SW2019到SW2023等多版本自动连接
  2. 健壮性设计:多重异常捕获机制+自动关闭残留进程
  3. 进度可视化:实时显示转换进度与预计剩余时间
  4. 配置持久化:自动记忆上次操作路径提升重复使用效率

运行代码

运行代码之后需要在控制台进行输入配置,具体流程为:

输入SLDPRT目录 → 确认输出路径 → STL输出目录 → 确认输出路径 → 自动批量转换 

软件配置

在运行过程中,会弹出来SolidWorks软件,你不需要做任何事,只需要等待完成即可。

弹出来SolidWorks

© 版权声明
THE END
喜欢就支持一下吧
点赞 0 分享 赞赏
评论 抢沙发
上传图片
OωO
取消