为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕工程0101907 2021-08-05 17:16:27
如果我要在 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 = Trueself._python_resource是一个由 Python GC 管理的资源包装器对象,self._external_resource是一个不受 Python GC 管理的外部资源的句柄。如果用户手册关闭包装器,我想确保托管和非托管资源都被释放,如果包装器对象被 GC,它们也会被释放。
查看完整描述

1 回答

?
慕慕森

TA贡献1856条经验 获得超17个赞

不,在 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")),它将是有效的。


查看完整回答
反对 回复 2021-08-05
  • 1 回答
  • 0 关注
  • 214 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号