Closing a connection with a `with` statement
<p>I want to have a class that represents an IMAP connection and use it with a <code>with</code> statement as follows:</p>

<pre><code>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)
</code></pre>

<p>Naturally this fails since <code>IMAPConnections</code> has no attribute <code>close</code>. How can I store the connection and pass it to the <code>__exit__</code> function when the <code>with</code> statement is finished?</p>

<p>You need to implement a <code>__exit__()</code> function within your <code>IMAPConnection</code> class.</p>

<p><code>__enter__()</code> function is called before executing the code within the <code>with</code> block where as <code>__exit__()</code> is called while exiting the <code>with</code> block.</p>

<p>Below is the sample structure:</p>

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

<p>Check: <a href="http://stackoverflow.com/a/1984346/2063361">Explaining Python's '<strong>enter</strong>' and '<strong>exit</strong>'</a> for more information.</p>

python imap with-statement imaplib