I am trying to get a threaded job server running that will thread
scripts to manipulate various MS office apps. My first attempt has
failed on Excel. It seems that invoking
win32com.client.Dispatch('Excel.Application') from within a thread
does not initialize the same way as it does when it is called from
within the main python environment. A simple example:
from threading import Thread
class foo:
def run(self):
try:
import win32com.client
self.excel = win32com.client.Dispatch("Excel.Application")
self.excel.Visible = 1
k = self.excel.Workbooks.Add()
v = k.Worksheets(1)
v.Cells(1,1).Value = str(self)
except:
import traceback
traceback.print_exc()
l = Thread(target = foo().run, #creates a new instance
name = 'foo',verbose = 1)
l.start()
This causes the following stack trace:
Traceback (most recent call last):
File "I:\F\P\sp\interfaces\dispatcher\testexcelinthread.py", line
18, in run
self.excel = win32com.client.Dispatch("Excel.Application")
File "d:\python21\win32com\client\__init__.py", line 94, in Dispatch
dispatch, userName =
dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
File "d:\python21\win32com\client\dynamic.py", line 81, in
_GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)
File "d:\python21\win32com\client\dynamic.py", line 72, in
_GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx,
pythoncom.IID_IDispatch)
com_error: (-2147221008, 'CoInitialize has not been called.', None,
None)
Is there an alternate initialization procedure that will work from
within a Thread?
Any help would be greatly appreciated.
Stephen
[...]
> from threading import Thread
>
> class foo:
> def run(self):
> try:
> import win32com.client
# You have to use pythoncom.CoInitialize and pythoncom.CoUninitialize eg.:
import pythoncom
pythoncom.CoInitialize()
> self.excel = win32com.client.Dispatch("Excel.Application")
pythoncom.CoUninitialize()
> self.excel.Visible = 1
> k = self.excel.Workbooks.Add()
> v = k.Worksheets(1)
> v.Cells(1,1).Value = str(self)
> except:
> import traceback
> traceback.print_exc()
Cheers
Adam Karpierz
karp...@zope.pl
> # You have to use pythoncom.CoInitialize and pythoncom.CoUninitialize eg.:
For all threads other than the main thread, correct.
>
> import pythoncom
> pythoncom.CoInitialize()
>
>
>> self.excel = win32com.client.Dispatch("Excel.Application")
>
>
> pythoncom.CoUninitialize()
>
>
>> self.excel.Visible = 1
>> k = self.excel.Workbooks.Add()
>> v = k.Worksheets(1)
>> v.Cells(1,1).Value = str(self)
>> except:
>> import traceback
>> traceback.print_exc()
>
This is wrong though. It should look more like:
import pythoncom
pythoncom.CoInitialize()
self.excel = win32com.client.Dispatch("Excel.Application")
self.excel.Visible = 1
k = self.excel.Workbooks.Add()
v = k.Worksheets(1)
v.Cells(1,1).Value = str(self)
# Remove all refs, then uninit.
self.excel = None
k = v = None
pythoncom.CoUninitialize()
ie, CoUninitialize should be the last thing done on a thread, and only
done after all references to objects created on that thread have been
destroyed.
Storing a thread-created COM object in your instance (ie, self.excel) is
a recipe for disaster, but I haven't time to go there now!
Mark.
running various MS office apps automatically can also be a recipe for
disaster. Word, in particular, can only have one instance going at a time
else it will do all the work into the same document. that is, if there are
2 scripts automating word they will both be automating the same document,
and likely crashing it.
to this end, i have been working on a spooler for word automation. you can
find the gist at http://ecpspooler.sourceforge.net. contact me if you are
interested.
-doug
Thanks, works like a charm! This last bit is a little ominous ...
>
> Storing a thread-created COM object in your instance (ie, self.excel) is
> a recipe for disaster, but I haven't time to go there now!
>
> Mark.
.. Is there a description or example in one of your books?
Stephen
> This is wrong though. It should look more like:
Of course :)
Sorry for my mistake.
Adam Karpierz
karp...@zope.pl