显式调用"with"的__exit__并退出



我有一个类,可以在初始化时打开套接字连接,并可以与对方来回发送和接收某些消息。我使用with语句创建了该对象的一个实例。在我的类中,如果我在套接字上收到某些消息,我希望显式关闭连接,并退出with语句。

我试图通过显式调用self.__exit__(None, None, None) 来做到这一点

def __exit__(self, type, value, traceback):
    print 'Closing Connection'
    self.logout()
    self.conn.close()
    sys.exit(1)

然而,我发现我收到了两次Closing Connection消息,并且遇到了问题,因为在第二次呼叫中,不再有要关闭的连接。通过检查代码,我已经排除了对self.__exit__(None, None, None)进行显式调用的所有其他实例。怎么回事?sys.exit(1)是否不足以防止with再次进行垃圾收集(尽管从我所读到的内容来看,这似乎是最"认可"的方法)?如何防止with语句调用self.__exit__(None, None, None)。如果有任何帮助,或是正确的方向,我们将不胜感激!

一旦进入with语句,在不运行__exit__的情况下离开的唯一方法就是使用os._exit;那太糟糕了。相反,如果您想要这种行为,请明确地从调用__enter__开始。或者,如果像@Kay在回答中建议的那样被调用两次,请更改你的类,以确保它不会进行两次清理。或者,按照@IsmailBadawi在评论中的建议,重构代码,这样就不需要显式调用__exit__

只要记住你是否已经关闭了连接/log/something:

class MyContext(object):
    def __init__(self):
        self.__already_closed = False
    ....
    def close(self):
        if not self.__already_closed:
            self.__already_closed = True
            self.logout()
            self.conn.close()
    def __exit__(...):
        self.close()

甚至可能添加一个"请不要清理"的方法:

    def do_not_cleanup(self):
        self.__already_closed = True

最新更新