How to close an Excel instance if the Python console program gets interrupted and closed?

扶醉桌前 提交于 2021-01-29 08:31:27

问题


I'm trying to figure out how to close an Excel instance properly if the Python console program is interrupted and closed while executing.

Below is a minimal reproducible example:

# import pythoncom
import traceback
import win32com.client
import win32api

def exit_handler(arg):
  file = open('Log.txt', 'w')
  file.write(f'{repr(workbook)}\n{repr(excel_application)}\n')
  try:
    # pythoncom.CoInitialize()
    workbook.Close(SaveChanges=False)
    excel_application.Quit()
  except Exception:
    file.write(traceback.format_exc())
  finally:
    file.close()

excel_application = win32com.client.DispatchEx(clsid='Excel.Application')
workbook = excel_application.Workbooks.Add()
win32api.SetConsoleCtrlHandler(exit_handler, True)
input('Don\'t press the "Enter" key.\nClose the console by clicking the top right "X" button or by pressing the "Alt" + "F4" keys.\n')
# The input is just to pause the program for the user to close the console before it finishes executing. If it does finish executing the function exit_handler won't run.

I'm handling the exit event in the function exit_handler which is set by win32api.SetConsoleCtrlHandler and runs if the console is closed by the user.

I can execute workbook.Close(SaveChanges=False) and excel_application.Quit() outside of the function without any problem when the console isn't being closed but when I run it inside I get an error/exception.

The resulting Log.txt file gets the following content:

<win32com.gen_py.None.Workbook>
<win32com.gen_py.Microsoft Excel 15.0 Object Library._Application instance at 0x10283920>
Traceback (most recent call last):
  File "PathCensored\Excel.py", line 9, in exit_handler
    workbook.Close(SaveChanges=False)
  File "C:\Users\UserNameCensored\AppData\Local\Temp\gen_py\3.7\00020813-0000-0000-C000-000000000046x0x1x8\_Workbook.py", line 71, in Close
    , Filename, RouteWorkbook)
pywintypes.com_error: (-2147221008, 'CoInitialize has not been called.', None, None)

If I uncomment the import pythoncom and pythoncom.CoInitialize() lines in their respective place the Log.txt file gets the following content instead:

<win32com.gen_py.None.Workbook>
<win32com.gen_py.Microsoft Excel 15.0 Object Library._Application instance at 0x44609616>
Traceback (most recent call last):
  File "PathCensored\Excel.py", line 11, in exit_handler
    workbook.Close(SaveChanges=False)
  File "C:\Users\UserNameCensored\AppData\Local\Temp\gen_py\3.7\00020813-0000-0000-C000-000000000046x0x1x8\_Workbook.py", line 71, in Close
    , Filename, RouteWorkbook)
pywintypes.com_error: (-2147417842, 'The application called an interface that was marshalled for a different thread.', None, None)

The Close function in the file C:\Users\UserNameCensored\AppData\Local\Temp\gen_py\3.7\00020813-0000-0000-C000-000000000046x0x1x8\_Workbook.py is:

    def Close(self, SaveChanges=defaultNamedOptArg, Filename=defaultNamedOptArg, RouteWorkbook=defaultNamedOptArg):
        return self._oleobj_.InvokeTypes(277, LCID, 1, (24, 0), ((12, 17), (12, 17), (12, 17)),SaveChanges
            , Filename, RouteWorkbook)

Related questions that I have checked to try to find a solution:

Python - Windows Shutdown Events

python3 ctype CreateWindowEx simple example

Python - How to detect when user closes a console application via “X” button

How do i catch system Logoff/ShutDown/Lock events in Python or PyQt4

Python Save Sets To File On Windows Shutdown?

Using win32com with multithreading

How to handle console exit and object destruction

Python, How to close excel workbook if user prematurely closes the command prompt?

来源:https://stackoverflow.com/questions/63037454/how-to-close-an-excel-instance-if-the-python-console-program-gets-interrupted-an

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!