[python-win32] COM and threading

Tim Golden mail at timgolden.me.uk
Fri Jun 27 17:56:52 CEST 2008


June Kim wrote:
> Running the following code results in an attribute error:
> 
> Exception in thread Thread-1:
> Traceback (most recent call last):
>   File "C:\Python25\lib\threading.py", line 486, in __bootstrap_inner
>     self.run()
>   File "testcom.py", line 10, in run
>     print self.ie.locationUrl
>   File "C:\Python25\Lib\site-packages\win32com\client\dynamic.py", line 500, in
> __getattr__
>     raise AttributeError, "%s.%s" % (self._username_, attr)
> AttributeError: InternetExplorer.Application.locationUrl
> 
> It seems like the COM object isn't properly passed to the new thread.
> Any roundabouts?

Welcome to the wonderful world of COM and threading. Basically,
the IWebBrowser2 object which is behind the InternetExplorer
control cannot be passed as such between threads. To pass it
between threads you need to marshal it and pass the resulting 
istream to the other thread which will then unmarshal it again.

There's some sample code below which does this, but you might
want to consider another approach, depending on what your app
is trying to do, such as creating an IE object per thread and/or
passing native Python objects between threads with Queues etc.

TJG

<code>
import os, sys
import threading
import time

import pythoncom
import win32com.client

class Work (threading.Thread):
  
  def __init__ (self, marshalled_ie):
    threading.Thread.__init__ (self)
    self.marshalled_ie = marshalled_ie
  
  def run (self):
    pythoncom.CoInitialize ()
    ie = win32com.client.Dispatch (
      pythoncom.CoGetInterfaceAndReleaseStream (
        self.marshalled_ie, 
        pythoncom.IID_IDispatch
      )
    )
    print "Threaded LocationURL:", ie.LocationURL
    pythoncom.CoUninitialize ()

ie = win32com.client.Dispatch ("InternetExplorer.Application")
ie.Visible = 1
ie.Navigate ("http://python.org")
while ie.Busy: 
  time.sleep (1)
print "LocationURL:", ie.LocationURL

marshalled_ie = pythoncom.CoMarshalInterThreadInterfaceInStream (
  pythoncom.IID_IDispatch, ie
)
work = Work (marshalled_ie)
work.start ()
work.join ()

ie.Quit ()

</code>


More information about the python-win32 mailing list