>> 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