>> I'm experimenting with a pythoncom client which uses a ctypes.com
>> server.  I have the impression that DispatchWithEvents somehow doesn't
>> clean up correctly.
>
> That is possible.  Most leaks of COM objects should be evident by querying
> pythoncom._GetInterfaceCount() and pythoncom._GetGatewayCount() - it would
> be interesting to know if these were both zero and you still had the
> problem.

Here is the program I use, it is accessing a localserver COM object:

"""
# ctypes client code, using the CSum COM object
from win32com.client import Dispatch, DispatchWithEvents
import pythoncom

class events:
    def OnAdded(self, *args):
        print "OnAdded", args

def test():
    s = DispatchWithEvents("ctypes.SumObject", events)
##    s = Dispatch("ctypes.SumObject")
    print "Adding"
    print s.Add(3.14, 2.78)
    del s

    print "pythoncom._GetInterfaceCount():", pythoncom._GetInterfaceCount()
    print "pythoncom._GetGatewayCount():", pythoncom._GetGatewayCount()

    print "pythoncom.CoUninitialize()"
    pythoncom.CoUninitialize()

    print "pythoncom._GetInterfaceCount():", pythoncom._GetInterfaceCount()
    print "pythoncom._GetGatewayCount():", pythoncom._GetGatewayCount()
    

if __name__ == "__main__":
    test()
"""

and the output:

"""
C:\sf\ctypes_dist\win32\com\samples\server>py23 w32_user.py
Adding
OnAdded ()
5.92
pythoncom._GetInterfaceCount(): 1
pythoncom._GetGatewayCount(): 3
pythoncom.CoUninitialize()
pythoncom._GetInterfaceCount(): 0
pythoncom._GetGatewayCount(): 0

C:\sf\ctypes_dist\win32\com\samples\server>
"""

>> Is there a reason why pythoncom doesn't call CoUninitialize() itself?
>
> We had a few problems trying to do that.  In some cases when not all COM
> objects were explicitly closed, we found that system shutdown time could
> cause the object to attempt to release the COM pointer - but *after*
> CoUninit had been called.  But I have found very few errors *not* calling
> it - especially when all COM objects have been cleaned up.  I guess that is
> really just a matter of finding the correct hook (but note that in a COM DLL
> case, Python itself will never be Uninitialized!

ctypes.com uses this strategy to initialize and deinitialize (the code
is part of the ctypes.com module):

"""
ole32.CoInitialize(None)

class _Cleaner(object):
    def __del__(self, func=ole32.CoUninitialize):
        # Sometimes, CoUnititialize, running at Python shutdown, raises an 
exception.
        # We suppress this when __debug__ is False.
        if __debug__:
            func()
        else:
            try: func()
            except WindowsError: pass

__cleaner = _Cleaner()
del _Cleaner

def _clean_exc_info():
    # the purpose of this function is to ensure that no com object
    # pointers are in sys.exc_info()
    try: 1//0
    except: pass

import atexit
atexit.register(_clean_exc_info)
"""

Thomas

_______________________________________________
Python-win32 mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-win32

Reply via email to