The following code works well, but it fails if executed from a CherryPy app method with the error message CoInitialize has not been called
:
import win32com.client
xl = win32com.client.Dispatch("Excel.Application")
xl.quit()
This post suggests a solution that works for me:
import pythoncom
pythoncom.CoInitialize()
The reason I'm asking about a problem for which I already have a solution, is that (1) I would like to know what I'm doing (rather than doing it only because I've seen it working once) and (2) I don't want to risk to miss something important (and reading this post makes me think that I am missing something.)
I couldn't find any documentation for pythoncom.CoInitialize()
, and the source of pythoncom is the following three lines that don't help me (nor Eclipse+pydev which says that the method does not exist):
# Magic utility that "redirects" to pythoncomxx.dll
import pywintypes
pywintypes.__import_pywin32_system_module__("pythoncom", globals())
CoInitialize() predates the COM threading models, so it initializes a new single-threaded apartment for the thread. CoInitializeEx() takes an additional parameter that allows you to specify the threading model; thus, you must use this function to have your thread in the free-threading apartment.
The win32com. client package contains a number of modules to provide access to automation objects. This package supports both late and early bindings, as we will discuss. To use an IDispatch-based COM object, use the method win32com.client.Dispatch().
Pywin32 is basically a very thin wrapper of python that allows us to interact with COM objects and automate Windows applications with python. The power of this approach is that you can pretty much do anything that a Microsoft Application can do through python.
I can't remember exactly as I didn't work with COM last years but I guess that you have to initialize COM in every thread you work with it (again I'm not sure about every COM compartment). As CherryPy is threaded servers your requests are handled by different threads, not one you bootstrap with. So I suggest you to try the following in your bootstrap routine:
import pythoncom
def onThreadStart(threadIndex):
pythoncom.CoInitialize()
cherrypy.engine.subscribe('start_thread', onThreadStart)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With