尝试最终装饰器来清理python对象

时间:2014-07-22 15:07:28

标签: python class python-2.7 decorator resource-cleanup

似乎对象清理是我在编程时遇到的一个非常常见的问题。到目前为止,我一直使用with语句作为建议here

今天我有另一个想法,对我来说似乎更优雅(因为它不需要最终用户的声明)。我们的想法是为某种类型的对象使用try-finally装饰器(有一个清理方法)。

只是想知道这种做法是否有任何问题,或者是否有更好的事情。我不喜欢我的许多类需要使用with语句进行初始化,但我也想确保我的对象正确关闭。这是一个简短的例子。

def cleanme(func):
    def _decorator(self, *args, **kwargs):
        try:
            func(self, *args, **kwargs)
        finally:
            self._cleanup()

    return _decorator


class IObject(object):
    def __init__(self):
        self.file_name = "some_file.txt"
        self._file_object = None
        self._cleaned = True

    @cleanme
    def run(self):
        self._connect()
        while True:
            # do some things over a long period
            pass

    def _connect(self):
        self._file_object = open(self.file_name)
        self._cleaned = False

    def _cleanup(self):
        if not self._cleaned:
            self._file_object.close()
            self._cleaned = True

2 个答案:

答案 0 :(得分:2)

让我在这里拍几个洞。

有人想到,你的课程必须要cleanup(),这被宣布不在与run()不同的地方。所以你强迫用户有责任干净地实施和维护它。

__exit__以外的析构函数在Python中非常罕见,因此资源获取代码可能会偏离cleanup()代码,从而导致泄漏。

其次,你正在使file_object成为一个实例变量,从而将其范围扩大到单个函数,这也有些不好。

答案 1 :(得分:2)

我认为只要您的客户只使用IOObject执行run所做的任何事情,并且不想直接致电connect,我认为此方法就可以了使用已打开的file_object执行其他操作。

上下文管理器使客户能够轻松地确切知道他们在哪里获取/清理资源,并且还可以让他们灵活地基本上做任何他们想要的事情,因为他们知道一旦他们离开了with阻止它将被清除。用这种方法不太清楚;客户端需要查看代码(或者可能是文档)才能知道run方法将为它们清理,但是如果直接使用connect,则需要cleanup被要求妥善清理。

还有Python的Zen规则" Excplicit比Implicit" 更好。 with语句明确显示正在获取和释放资源的客户端。你用装饰器的方法就失去了它。