Pproblems using Python, COM, Event (or Connection Point) and thread

Marc ENGEL marc.engel at recif.com
Tue Nov 20 04:20:39 EST 2001


Hi,

I found in example TestMarshal.py from win32com a beginning of
solution using CoMarshalInterThreadInterfaceInStream but I still don't
understand if it necessary to start 1 python interpeter for each
thread.
Is it possible to use CoMarshalInterThreadInterfaceInStream with
thread started from the same interpreter instance?

Marc ENGEL

marc.engel at recif.com (Marc ENGEL) wrote in message news:<6411841c.0111140134.48720bff at posting.google.com>...
> Dear all,
> 
> I am trying to do a kind of Event Manager in Python. The architecture
> I want is the following:
> - A main python scripts start all the COM object needed by the
> application with DispatchWithEvents and then wait for messages using
> PumpMessage
> - The EventManager registered to each COM object do litle processing:
> it just delegates the event processing to a new thread and return (I
> don't need to return a value for events)
> - The Threaded Event Manager do the actual processing and mainly I
> want it to
> call the method that can process the event on other COM objects. The
> Event manager may also do some additional processing depending on the
> event.
> 
> In order to test this, I started from the Excel event script example
> and I modify it. See script source at the end of the message. It is
> running on my computer
> 
> I have 2 problems:
> 1 - If I try to access the COM object in the Event Thread by
> uncommenting Target.Column in classe ExcelEvents (line >>> print
> "Column = "#, Target.Column), I get the following error:
> 
>   File "d:\program files\python21\win32com\client\__init__.py", line
> 334, in _ApplyTypes_
>     return self._get_good_object_(apply(self._oleobj_.InvokeTypes,
> (dispid, 0, wFlags, retType, argTypes) + args), user, resultCLSID)
> pywintypes.com_error: (-2147417842, "L'application a appel\xe9 une
> interface qui \xe9tait maintenue en ordre pour une thread
> diff\xe9rente.", None, None)
> 
> Sorry the error message is in french (but actually I am french :)). It
> means "Application has called an interface that was maintained in
> order for a different thread"
> 
> Any hint?
> 
> 2 - I would like that class EventManager does not define all events it
> can manage but dynamically create a function to be called for each
> event that it is asked to manage. I thought it would be intersting to
> use the magic method __getattr__ to create the method with the event
> name dynamically. But as you will see if you execute the script, this
> method is never called.
> 
> Is there anything I did not understand about this method?
> 
> Thanks for any hint,
> 
> Marc ENGEL
> 
> -----------------> Start Python script
> import sys, time, msvcrt, win32com.client, win32gui, thread, win32ui,
> win32api, win32con
> 
> sys.coinit_flags = 0 #COINIT_MULTITHREADED    
> #COINIT_APARTMENTTHREADED = 0x02
> 
> import pythoncom
> 
> class EventsManager :
> 	def __getattr__(self, attr):
> 		print "Trying to call event ", attr
> 		args=self._prop_map_get_.get(attr)
> 		if args is None:
> 			raise AttributeError, attr
> 		return apply(self._ApplyTypes_, args)
> 	# Default handler for Event OnSheetBeforeDoubleClick
> 	# Delegates treatment to class ExcelEvents into a new thread
> 	def OnSheetBeforeDoubleClick(self, Sh, Target, Cancel):
> 		thread.start_new_thread(ExcelEvents().OnSheetBeforeDoubleClick, (Sh,
> Target, Cancel))
> 		return 0
> 
> class ExcelEvents:
> 	def OnSheetBeforeDoubleClick(self, Sh, Target, Cancel):
> 		pythoncom.CoInitializeEx(0)
> 		print "Column = "#, Target.Column
> 		time.sleep(5)
> 		print "Finished processing event for column "#, Target.Column
> 		pythoncom.CoUninitialize()
> 		return 0
> 
> 
> def ThreadWaitingForUserInput() :
> 	win32api.MessageBox(0, "Press OK when you want to stop the message
> loop", "Info")
> 	# Post message to dummy window in order to get out of the main event
> loop PumpMessages
> 	win32gui.PostMessage(MyDummyWindow, win32con.WM_QUIT, 0, 0)
> 	return 0
> 
> # Create new Execel application
> excel = win32com.client.DispatchWithEvents("Excel.Application",
> EventsManager)
> excel.Visible=1
> excel.Workbooks.Add()
> 
> # Create a dummy window for posting WM_QUIT message
> MyDummyWindow = win32gui.CreateWindow("BUTTON", "TestWindow", 0, 0, 0,
> 100, 100, 0, 0, 0, None)
> 
> # Start new thread to display the MessageBox to exit application
> thread.start_new_thread(ThreadWaitingForUserInput, ())
> # Give it a chance to start
> win32api.Sleep(100)
> win32ui.PumpWaitingMessages()
> 
> # Main event loop waiting for quit message posted from thread
> ThreadWaitingForUserInput
> pythoncom.PumpMessages()
> print "Quitting script..."
> 
> # Don't want dialog box for saving document before closing Excel
> excel.DisplayAlerts = 0
> # Remove the workbook
> excel.Workbooks.Close()
> # Quit application
> excel.Quit()
> # Release excel object
> excel = None
> 
> # This is just a trick to have the script displaying error message if
> any!
> print "Press OK on Popup Message box to stop scipt..."
> win32api.MessageBox(0, "Press OK to stop script", "Info")
> 
> -----------------> End Python script



More information about the Python-list mailing list