我是否需要在 Python 中为资源包装器实现 Dispose 模式

如果我要在 Python 中实现一个安全的资源包装器,我是否需要像 C# 一样实现Dispose 模式?


这是我的意思的演示实现:


class ResourceWrapper:

    def __init__(self):

        self._python_resource = ...  # A Python object that manages some resources.

        self._external_resource = _allocate_resource()  # A resource handle to an external resource.

        self._is_closed = False  # Whether the object has been closed.


    def __del__(self):

        self._close(manual_close=False)  # Called by GC.


    def close(self):

        self._close(manual_close=True)  # Called by user to free resource early.


    def _close(self, manual_close):

        if not self._is_closed:  # Don’t want a resource to be closed more than once.

            if manual_close:

                # Since `_close` is called by user, we can guarantee that `self._python_resource` is still valid, so we

                # can close it safely.

                self._python_resource.close() 

            else:

                # This means `_close` is called by GC, `self._python_resource` might be already GCed, but we don’t know

                # for sure, so we do nothing and rely on GC to free `self._python_resource`.


                pass


            # GC will not take care of freeing unmanaged resource, so whether manual close or not, we have to close the

            # resource to prevent leaking.


            _free_resource(self._external_resource)


            # Now we mark the object as closed to prevent closing multiple times.


            self._is_closed = True

self._python_resource是一个由 Python GC 管理的资源包装器对象,self._external_resource是一个不受 Python GC 管理的外部资源的句柄。


如果用户手册关闭包装器,我想确保托管和非托管资源都被释放,如果包装器对象被 GC,它们也会被释放。


慕工程0101907
浏览 273回答 1
1回答

慕慕森

不,在 Python 中你应该使用Context Managers:class ResourceWrapper:    def __init__(self):        ...    ...    def __enter__(self):        return self    def __exit__(self, type, value, traceback):        self._close(manual_close=False)with ResourceWrapper() as wrapper:    # do something with wrapper注1:方法中有这样的注释_close():这意味着_close被 GC 调用,self._python_resource可能已经被 GC,但我们不确定,所以我们什么都不做,依靠 GC 来释放self._python_resource.我不确定您的意思,但只要您持有对对象的引用(并且只要它不是弱引用),它就不会被 GC 处理。注 2:如果一个上下文管理器的对象在没有with阻塞的情况下使用会发生什么?然后当对象被垃圾收集时资源将被释放 - 但我不会担心。使用上下文管理器是 Python 中的常见习惯用法(请参阅任何带有open()ing 文件的示例)。如果这对您的应用程序至关重要,您可以在 中获取资源__enter__(),除非在with块中否则不会获取资源。注意 3,关于循环引用:如果你有两个对象相互持有引用,你就形成了循环引用,这样两个对象就不会被“常规”引用计数 GC 释放。相反,它们将由分代 GC 收集,除非他们碰巧有__del__方法。__del__禁止 GC 收集对象。见gc.garbage:收集器发现无法访问但无法释放的对象列表(不可收集的对象)。默认情况下,此列表仅包含带有__del__() methods. [1] 具有__del__()方法并且是引用循环的一部分的对象 会导致整个引用循环不可收集,包括不一定在循环中但只能从循环中访问的对象。Python 3.4 引入了PEP-442,它引入了安全对象终结。无论哪种方式,您都不会有无效的引用。如果您有属性 ( hasattr(self, "_python_resource")),它将是有效的。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python