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