在Python上使用win32com无法完全关闭Excel

wkftcu5l  于 2023-03-04  发布在  Python
关注(0)|答案(7)|浏览(362)

这是我的代码,我找到了很多关于VBA,.NET框架的答案,很奇怪。当我执行这个代码时,Excel关闭。

from win32com.client import DispatchEx
excel = DispatchEx('Excel.Application')
wbs = excel.Workbooks
wbs.Close()
excel.Quit()
wbs = None
excel = None # <-- Excel Closes here

但是当我做下面的操作时,它并没有关闭。

excel = DispatchEx('Excel.Application')
wbs = excel.Workbooks
wb = wbs.Open('D:\\Xaguar\\A1.xlsm')
wb.Close(False)
wbs.Close()
excel.Quit()
wb = None
wbs = None
excel = None  # <-- NOT Closing !!!

我在堆栈溢出问题 Excel process remains open after interop; traditional method not working 中找到了一些可能的答案。问题是这不是Python,我没有找到Marshal.ReleaseComObjectGC。我看了...site-packages/win32com和其他的所有演示。
即使它不打扰我,如果我可以得到的PID和杀死它。
我在 Kill process based on window name (win32) 中找到了一个变通方法。
可能不是正确的方法,但变通办法是:

def close_excel_by_force(excel):
    import win32process
    import win32gui
    import win32api
    import win32con

    # Get the window's process id's
    hwnd = excel.Hwnd
    t, p = win32process.GetWindowThreadProcessId(hwnd)
    # Ask window nicely to close
    win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0)
    # Allow some time for app to close
    time.sleep(10)
    # If the application didn't close, force close
    try:
        handle = win32api.OpenProcess(win32con.PROCESS_TERMINATE, 0, p)
        if handle:
            win32api.TerminateProcess(handle, 0)
            win32api.CloseHandle(handle)
    except:
        pass

excel = DispatchEx('Excel.Application')
wbs = excel.Workbooks
wb = wbs.Open('D:\\Xaguar\\A1.xlsm')
wb.Close(False)
wbs.Close()
excel.Quit()
wb = None
wbs = None
close_excel_by_force(excel) # <--- YOU #@#$# DIEEEEE!! DIEEEE!!!
wvmv3b1j

wvmv3b1j1#

试试这个:

wbs.Close()
excel.Quit()
del excel # this line removed it from task manager in my case
pprl5pva

pprl5pva2#

对我有效的是确保取消引用你在过程沿着赋值的任何变量,如下所示:

import win32com.client as win32

fileDirectory = 'Hello World.xlsx'

#excelFile = win32.Dispatch('Excel.Application')
excelFile = win32.gencache.EnsureDispatch('Excel.Application')

excelFile.Visible = True
excelFile.DisplayAlerts = True

wb = excelFile.Workbooks.Open(fileDirectory)
ws = wb.Sheets("Sell")

ws.Range("D1").Value = "Hello World!"
ws = None

wb.Close(False)
wb = None

excelFile.Quit()
excelFile = None

它适用于任何调度格式。

643ylb08

643ylb083#

我发现通过win32com杀死一个Excel进程并不总是那么可靠,这包括上面建议的excel.Application.Quit()del excel
我发现确保它已停止的唯一方法是物理地终止EXCEL.EXE进程:

import psutil

def kill_excel():
    for proc in psutil.process_iter():
        if proc.name() == "EXCEL.EXE":
            proc.kill()

缺点是,这个脚本显然会杀死当前运行的所有excel进程。如果你能接受这一点,那么这不是一个坏的选择。

baubqpgj

baubqpgj4#

我有这个在我的文件使用Excel:

self.excel.Application.Quit()
zmeyuzjn

zmeyuzjn5#

Python应该处理COM对象的生命周期,只需设置excel = None,参考如下:

# CH9 says: Python manages COM lifetimes automatically for you; when your excel 
#           variable is no longer used, Excel automatically closes. In Python,
#           the simplest way to remove this variable is to assign it to another 
#           value. If you use the following code, notice that Excel vanishes 
#           from the screen; it knows there are no longer any programs referring to it.

来源:
http://www.icodeguru.com/WebServer/Python-Programming-on-Win32/ch05.htm#:~:text=xl%20=%20None

vaqhlq81

vaqhlq816#

对于任何来自搜索引擎的新人:
在我的试验中,这个答案说正确的Python应该处理COM对象的生命周期......只要设置excel = None,Excel.exe PID就会立即或稍后自动关闭。如果你仍然发现Excel.exe存在很长时间,请调用python gc collect。

import gc
gc.collect()
ssm49v7z

ssm49v7z7#

大多数其他的答案都是利用完全杀死Excel。问题是,这将关闭任何其他可能已经打开的Excel示例。
要使打开的工作簿真正关闭,需要关闭并删除工作簿(返回值来自excel.Workbooks.Open)。

import win32com.client

excel = win32com.client.Dispatch('Excel.Application')
workbook = excel.Workbooks.Open(r'your\excel\file.xlsm')
# Do whatever you need to with the workbook
workbook.Close(False)  # or workbook.Close(True) if you want to save it
del(workbook)

这可以封装在一个try ... except ...块中,以确保即使出现错误也能关闭它。

import win32com.client
import logging

excel = win32com.client.Dispatch('Excel.Application')
workbook = excel.Workbooks.Open(r'your\excel\file.xlsm')
try:
    some_function_to_use_workbook(workbook)
    workbook.close(True)
except Exception as error:
    logging.error(error)
    workbook.close(False)
finally:
    del(workbook)

如果出于某种原因,你真的需要关闭Excel并关闭所有打开的工作簿,那么你需要强制关闭所有工作簿,退出应用程序并删除Excel对象。

import win32com.client

excel = win32com.client.Dispatch('Excel.Application')
workbook = excel.Workbooks.Open(r'your\excel\file.xlsm')
# Do whatever you need to with the workbook
workbook.Close(False)
del(workbook)
excel.Workbooks.Close()
excel.Application.Quit()
del(excel)

相关问题