首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python多个非托管资源和异常安全

Python多个非托管资源和异常安全
EN

Stack Overflow用户
提问于 2016-01-27 03:51:25
回答 1查看 275关注 0票数 4

假设我希望有一个包含多个非托管资源的类,比如文件。我还希望该类的公共接口允许用户以异常安全的方式使用它,即不泄漏非托管资源/将它们置于垃圾收集器的摆布之下,垃圾收集器永远不能保证在任何时候运行(确定性资源回收)。

以下面的案例为例:

代码语言:javascript
复制
class Gizmo(object):
    def __init__(self, filepath1, filepath2):
        self._file1 = open(filepath1, 'rb')
        self._file2 = open(filepath2, 'rb')

    def __enter__(self):
        return self

    def __exit__(self):
        self.close()
        return False

    def __del__(self):
        self.close()

    def frob(self):
        ...manipulate the files...

    def close(self):
        self._file1.close()
        self._file2.close()

这不是异常安全的,因为如果在__init__中打开第二个文件的行失败,第一个文件就会泄漏,因为它将任由垃圾收集器摆布(无论我是否通过with-statement使用类)。

我的问题是:实现我想要的东西的最干净的方法是什么,最好是能够扩展到两个以上的非托管资源的方式,并且不会对我的类的公共接口造成太严重的混乱(如果有的话)?我想到了将初始化方法与__init__方法分开的想法,但这听起来有点奇怪。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-27 04:06:31

如果你使用的是Python3,这看起来像是contextlib.ExitStack的工作。如果您使用的是Python2,似乎可以使用此功能的backport

代码语言:javascript
复制
from contextlib import ExitStack

class Gizmo(object):
    def __init__(self, filepath1, filepath2):
        with ExitStack() as stack:
            # If opening the second file fails,
            # unwinding the stack will close the first file.

            self._file1 = stack.enter_context(open(filepath1, 'rb'))
            self._file2 = stack.enter_context(open(filepath2, 'rb'))

            # It worked! But we don't want to close the files when the with statement ends.
            # Take the files off the stack without closing them
            # (and put them on a new stack).
            self._exitstack = stack.pop_all()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, exc_tb):
        return self._exitstack.__exit__(exc_type, exc_value, exc_tb)

    def __del__(self):
        self.close()

    def frob(self):
        ...manipulate the files...

    def close(self):
        # __del__ will try to close a Gizmo even if we couldn't set up its _exitstack,
        # so don't try to close a nonexistent _exitstack.
        if hasattr(self, '_exitstack'):
            # The stack calls __exit__ on all the files, exactly as if we were
            # exiting a "with open(...) as file1, open(...) as file2" block.
            # If closing one file fails, we'll still try to close the other.
            self._exitstack.close()
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35022619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档