Python用PyInstaller打包调用Autodesk Inventor COM对象报错求助
问题
我正在开发一个Python脚本,通过COM对象创建Autodesk Inventor实例并打开装配文件。脚本直接运行正常,但用PyInstaller打包成二进制文件后,运行时抛出以下错误:
Traceback (most recent call last): File "<path>\main.py", line 49, in <module> commands[vars(options)['command']](vars(options)) File "actions\createbatch.py", line 20, in run_create_batch_command File "actions\createbatch.py", line 31, in create_batch_with_references File "inventor.py", line 37, in open_doc_with_thread File "win32com\client\__init__.py", line 585, in __getattr__ File "win32com\client\__init__.py", line 574, in _ApplyTypes_ File "win32com\client\dynamic.py", line 638, in __getattr__ AttributeError: Inventor.Application.InvokeTypes [45208] Failed to execute script 'main' due to unhandled exception!
问题定位到以下代码的第10行(oApp.Documents.Open(path_to_file)):
try: oApp = win32com.client.Dispatch('Inventor.Application') # get COM object except pythoncom.com_error: raise AppNotFoundError() mod = gencache.EnsureModule('{D98A091D-3A0F-4C3E-B36E-61F62068D488}', 0, 1, 0) # Loads python support oApp = mod.Application(oApp) try: oApp.Documents.Open(path_to_file) except pythoncom.com_error: pass # throws error when app is closed before document can open
已排除gencache.EnsureModule无法加载模块的可能,尝试过不同版本的PyInstaller、Python,换机器编译都未解决问题。
解决方案
方法1:改用动态调度,跳过强类型绑定
删除通过gencache.EnsureModule生成强类型对象的代码,直接使用Dispatch返回的动态对象操作:
try: oApp = win32com.client.Dispatch('Inventor.Application') except pythoncom.com_error: raise AppNotFoundError() # 移除mod = gencache.EnsureModule(...)和oApp = mod.Application(oApp)这两行 try: oApp.Documents.Open(path_to_file) except pythoncom.com_error: pass
动态调度不依赖预生成的类型文件,打包后不会出现类型引用缺失的问题,缺点是失去代码补全功能,但能彻底解决打包后的运行错误。
方法2:手动生成并包含类型库文件
生成类型文件:在脚本运行环境中执行以下代码,生成Inventor对应的Python类型文件:
from win32com.client import makepy makepy.main(["{D98A091D-3A0F-4C3E-B36E-61F62068D488}"])生成的文件位于
Lib\site-packages\win32com\gen_py目录下对应CLSID的文件夹中。修改导入逻辑:将生成的类型文件复制到项目目录,直接导入模块替代
gencache逻辑:import sys sys.path.insert(0, "./path/to/generated_files") # 替换为实际生成的文件名,格式类似{D98A091D-3A0F-4C3E-B36E-61F62068D488}-0x1-0.py from {D98A091D-3A0F-4C3E-B36E-61F62068D488}-0x1-0.py import Application try: oApp = win32com.client.Dispatch('Inventor.Application') except pythoncom.com_error: raise AppNotFoundError() oApp = Application(oApp) try: oApp.Documents.Open(path_to_file) except pythoncom.com_error: pass打包时包含文件:在PyInstaller的spec文件中添加该类型文件到
datas:datas=[('./path/to/generated_files/{D98A091D-3A0F-4C3E-B36E-61F62068D488}-0x1-0.py', '.')]然后使用spec文件打包:
pyinstaller your_script.spec
方法3:让PyInstaller收集win32com缓存模块
打包时添加参数,让PyInstaller自动收集gen_py下的Inventor类型模块:
pyinstaller --collect-submodules win32com.gen_py your_script.py
或者在spec文件的Analysis部分添加到hiddenimports:
hiddenimports=['win32com.gen_py.{D98A091D-3A0F-4C3E-B36E-61F62068D488}']
内容的提问来源于stack exchange,提问作者Jon Zavialov
相关产品推荐
相关产品推荐

