-
-
Notifications
You must be signed in to change notification settings - Fork 104
Description
I wonder, is it possible to release a COM interface pointer manually by calling Release(), instead of waiting for its __del__ to be called?
The problem of this method is that Release() is still called when __del__ is called.
comtypes/comtypes/_post_coinit/unknwn.py
Lines 272 to 284 in 5c564ec
| def __del__(self, _debug=logger.debug) -> None: | |
| "Release the COM refcount we own." | |
| if self: | |
| # comtypes calls CoUninitialize() when the atexit handlers | |
| # runs. CoUninitialize() cleans up the COM objects that | |
| # are still alive. Python COM pointers may still be | |
| # present but we can no longer call Release() on them - | |
| # this may give a protection fault. So we need the | |
| # _com_shutting_down flag. | |
| # | |
| if not type(self)._com_shutting_down: | |
| _debug("Release %s", self) | |
| self.Release() # type: ignore |
__del__() in Python cannot be used to achieve deterministic destruction, like destructors in C++ do. In the docs:
del() can be invoked when arbitrary code is being executed, including from any arbitrary thread.
This would cause some problems if I want a certain COM object to be released at or before a certain time.
Although CPython uses reference counting, so usually the object will be released when the last reference is removed, it isn't necessarily the case in other Python implementations.
A common solution is to use the context manager. Implement __enter__ and __exit__, so that it can be used in a with block, and be automatically released when leaving the with block. Many resource objects, such as files, already support the context manager protocol.