【问题标题】:Try-finally decorator to clean up python objectTry-finally 装饰器清理 python 对象
【发布时间】:2014-09-13 11:44:51
【问题描述】:

对象清理似乎是我在编程期间遇到的一个很常见的问题。迄今为止,我一直按照建议使用with 声明here

今天我有另一个想法,这对我来说似乎更优雅(因为它不需要最终用户的 with 语句)。想法是对某种类型的对象使用 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

【问题讨论】:

  • 'with' 的意义在于摆脱这种“以后清理一切”的想法,并明确说明您使用哪些资源。您应该将对象分成两部分,一个是资源(保存该文件对象并知道如何清理),另一部分使用它,“运行”方法应该是“with my_resources: while True: do_stuff() "。
  • 在使用许多 IO 样式对象时会变得非常混乱(比如我打开了 3 个套接字来接收数据、一个视频源对象和一些通信管道等)。相反,我可以只使用一个 connect 方法和一个 close 方法来处理每个方法。
  • 我想这可以解决这个问题:stackoverflow.com/questions/3024925/…

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


【解决方案1】:

让我在这上面打几个洞。

想一想,你要求你的班级有一个cleanup(),它被声明在与run()不同的地方。所以你要让用户有责任干净地实施和维护它。

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

其次,您将file_object 设为实例变量,从而将其范围从单个函数扩大,这也有点糟糕。

【讨论】:

    【解决方案2】:

    我认为这种方法是可以的,只要您的客户只会使用您的IOObject 来执行run 所做的任何事情,并且不想直接调用connect 然后使用@987654324 执行一些其他操作@ 已打开。

    上下文管理器使客户可以轻松准确地知道他们在哪里获取/清理资源,并且还使他们能够灵活地从本质上做他们想做的任何事情,知道他们一离开@987654325 @block 它将被清理。使用这种方法就不太清楚了。客户需要查看代码(或者可能是文档)才能知道run 方法将为他们清理,但如果直接使用connect,则需要调用cleanup 才能正确清理起来。

    还有 Python 的禅宗规则“显式优于隐式”with 语句显式地显示正在获取和释放资源的客户端。使用装饰器方法你会失去它。

    【讨论】:

      猜你喜欢
      • 2012-06-07
      • 2012-01-24
      • 2022-11-23
      • 1970-01-01
      • 2018-06-21
      • 2013-02-19
      • 1970-01-01
      • 2018-03-19
      • 1970-01-01
      相关资源
      最近更新 更多