Python中如何正确关闭COMObject?Jupyter复用内核运行MSProject报错求助
Jupyter中重复调用MS Project COM对象报错的解决思路
问题场景
在Python 3.6.4(Anaconda环境)的Jupyter Notebook中,首次运行以下访问Microsoft Project文件的代码无报错:
import win32com.client pjApp = win32com.client.Dispatch('MSProject.Application') pjApp.FileOpen('X:/test.mpp') pjApp.FileClose() pjApp.Quit() # 也尝试过 pjApp.Application.Quit() pjApp = None del pjApp
但不重启内核重复执行(或放入循环多次执行)时,会抛出错误:
AttributeError: MSPRoject.Application.FileOpen
尝试通过杀死WINPROJ.EXE进程解决无效,需优化COM对象的清理操作。
解决思路
1. 显式释放COM对象资源
单纯通过del或赋值None仅清除Python层面的引用,COM环境中可能仍残留无效对象。需使用win32com提供的释放方法:
import win32com.client import pythoncom # 创建对象并操作 pjApp = win32com.client.Dispatch('MSProject.Application') pjApp.FileOpen('X:/test.mpp') pjApp.FileClose() pjApp.Quit() # 显式释放COM对象 win32com.client.ReleaseDispatch(pjApp) pjApp = None del pjApp # 可选:初始化COM环境(若后续不再使用COM对象) pythoncom.CoUninitialize()
2. 优化进程清理的时机与方式
之前的杀进程操作可能时机过早,导致COM对象未完全退出。调整流程,先完成COM对象释放,再等待并清理残留进程:
import win32com.client import psutil import time # 业务操作 pjApp = win32com.client.Dispatch('MSProject.Application') pjApp.FileOpen('X:/test.mpp') pjApp.FileClose() pjApp.Quit() # 释放COM对象 win32com.client.ReleaseDispatch(pjApp) pjApp = None del pjApp # 等待进程正常退出 time.sleep(2) # 清理残留进程 for proc in psutil.process_iter(['name', 'pid']): if proc.info['name'] == "WINPROJ.EXE": try: proc.terminate() # 先优雅终止 proc.wait(timeout=3) except psutil.NoSuchProcess: pass except psutil.TimeoutExpired: proc.kill() # 超时则强制杀死
3. 每次执行前清理残留进程
在创建新的COM对象前,先检查并杀死所有WINPROJ.EXE进程,避免复用无效实例:
import psutil import win32com.client # 清理残留进程 for proc in psutil.process_iter(['name']): if proc.info['name'] == "WINPROJ.EXE": try: proc.kill() except: pass # 创建新COM对象并操作 pjApp = win32com.client.Dispatch('MSProject.Application') pjApp.FileOpen('X:/test.mpp') pjApp.FileClose() pjApp.Quit() # 释放资源 win32com.client.ReleaseDispatch(pjApp) pjApp = None del pjApp
4. 使用DispatchEx创建独立COM实例
Dispatch可能复用系统中已有的COM实例,改用DispatchEx强制创建全新实例,避免旧实例干扰:
import win32com.client # 使用DispatchEx创建独立实例 pjApp = win32com.client.DispatchEx('MSProject.Application') pjApp.FileOpen('X:/test.mpp') pjApp.FileClose() pjApp.Quit() # 释放资源 win32com.client.ReleaseDispatch(pjApp) pjApp = None del pjApp
内容的提问来源于stack exchange,提问作者N00b101
相关产品推荐
相关产品推荐

