Excel.exe process keeps on running if visible false after any error
Asked Answered
U

2

0

Usually I use the following code to open an excel workbook in the background:

import xlwings as xw

app = xw.App(visible=False)
wb = xw.Book(filename)
sheet = wb.sheets['sheet1']

I sometimes do not code correctly and get an error message when I execute a code containing the above lines (with visible=False). In this case, the EXCEL.EXE process stays open on the processes list (in windows task manager on windows 10) in the background. Is there a solution that closes the particular excel process in the background that is opend with the python code, if I receive an error message? Otherwise for each time the code is executed with an error one extra excel process gets added to the process list resulting in less performance.

Currently, my workaround is to add the following lines at the top of the python script, but this closes all excel processes:

import subprocess
subprocess.call(["taskkill", "/f", "/im", "EXCEL.EXE"])

My objective is to close only that particular process that is opend with the python script.

Unroot answered 7/12, 2020 at 21:2 Comment(2)
What's wrong with app.Quit() ?Barrator
I think you mean app.quit()Unroot
U
1

Preferred solution
xlwings added a solution in v0.24.3 to this problem:
[Enhancement] xlwings.App() can now be used as context manager, making sure that there are no zombie processes left over on Windows, even if you use a hidden instance and your code fails. It is therefore recommended to use it whenever you can, like so:

import xlwings as xw
with xw.App(visible=False) as app:
    wb = xw.Book("test.xlsx")
    sheet = wb.sheets['sheet1']
    # To evoke an error, I try to call an non-exisiting sheet here.
    nonexistent_sheet["A1"]

The with-line prevents that a EXCEL.EXE process stays open in windows task manager, even if you have an error in the code.

Solution before v24.0.3
Less elegant: Errors are caught by the except block, which means your main purpose of the script should be written in the try block.

import xlwings as xw
import traceback

app = xw.App(visible=False)
wb = xw.Book("test.xlsx")
sheet = wb.sheets['sheet1']

# Do what you want here. To evoke an error, I try to call an non-exisiting sheet here.
try:
    not_existing_sheet["A1"]

# Sources for except block: https://mcmap.net/q/36432/-how-can-i-write-a-try-except-block-that-catches-all-exceptions and https://mcmap.net/q/36432/-how-can-i-write-a-try-except-block-that-catches-all-exceptions
except BaseException:
    print(traceback.print_exc())
    app.quit()
Unroot answered 8/12, 2020 at 12:46 Comment(0)
R
1

I found this code snippet here. Using this psutil library it gets all the processes you have running, checks if a string is in the process (ie. Adobe, EXCEL) and kills those processes. This worked well using Python 3 and Windows 10 to kill Excel sessions that continued to run in the background after I had opened and "closed" them with Win32com.

import psutil

def main():
    '''Process kill function'''    
    for proc in psutil.process_iter():
        # check whether the process name matches
        # print(proc.name())
        if any(procstr in proc.name() for procstr in\
            ['Adobe', 'EXCEL']):
            print(f'Killing {proc.name()}')
            proc.kill()


if __name__ == "__main__":
    main()
Resourceful answered 21/4, 2021 at 15:28 Comment(1)
Could you extend your code so that the code only closes the process if an error message occurs? The process in the background that is opend with the python code should only close, if I receive an error message. Right now it just does the same job as the last code snippet in the question text.Unroot

© 2022 - 2024 — McMap. All rights reserved.