关于python:用`with`语句关闭连接

Closing a connection with a `with` statement

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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__函数?


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

1
2
3
4
5
6
7
8
9
10
11
12
13
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是所谓的连接。


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

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

以下是示例结构:

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

检查:解释Python的'enter'和'exit'以获取更多信息。