【问题标题】:Closing a connection with a `with` statement使用 `with` 语句关闭连接
【发布时间】:2017-01-31 01:32:17
【问题描述】:

我想要一个代表 IMAP 连接的类并将其与with 语句一起使用,如下所示:

class IMAPConnection:
    def __enter__(self):
        connection = imaplib.IMAP4_SSL(IMAP_HOST)

        try:
            connection.login(MAIL_USERNAME, MAIL_PASS)
        except imaplib.IMAP4.error:
            log.error('Failed to log in')

        return connection

    def __exit__(self, type, value, traceback):
        self.close()

with IMAPConnection() as c:
    rv, data = c.list()
    print(rv, data)

这自然会失败,因为IMAPConnections 没有属性close。当with 语句完成时,如何存储连接并将其传递给__exit__ 函数?

【问题讨论】:

    标签: python imap with-statement imaplib


    【解决方案1】:

    您需要在 IMAPConnection 类中实现 __exit__() 函数。

    __enter__() 函数在执行 with 块中的代码之前调用,而在退出 with 块时调用 __exit__()

    下面是示例结构:

    def __exit__(self, exc_type, exc_val, exc_tb):
        # Close the connection and other logic applicable
        self.connection.close()
    

    查看:Explaining Python's 'enter' and 'exit' 了解更多信息。

    【讨论】:

      【解决方案2】:

      您需要将连接存储在对象属性中。像这样的:

      class IMAPConnection:
          def __enter__(self):
              self.connection = imaplib.IMAP4_SSL(IMAP_HOST)
      
              try:
                  self.connection.login(MAIL_USERNAME, MAIL_PASS)
              except imaplib.IMAP4.error:
                  log.error('Failed to log in')
      
              return self.connection
      
          def __exit__(self, type, value, traceback):
              self.connection.close()
      

      您还想为您的班级实现list 方法。

      编辑:我刚刚意识到您的实际问题是什么。当您执行 with SomeClass(*args, **kwargs) as c c 不是 __enter__ 方法返回的值时。 cSomeClass 的实例。这是您从__enter__ 返回连接并假设c 表示连接的问题的根源。

      【讨论】:

      • 哈,明白了。谢谢!
      • 我在回答中添加了更多解释。希望对你有帮助
      猜你喜欢
      • 2011-05-22
      • 1970-01-01
      • 1970-01-01
      • 2019-08-15
      • 1970-01-01
      • 1970-01-01
      • 2012-07-29
      • 2011-11-29
      • 2015-09-25
      相关资源
      最近更新 更多