nesting context managers

Ulrich Eckhardt ulrich.eckhardt at dominolaser.com
Tue Dec 20 11:56:54 EST 2011


Am 20.12.2011 15:15, schrieb Ulrich Eckhardt:
> Let us assume I had a class HTTPClient that has a socket for HTTP and a
> logfile for filing logs. I want to make this HTTPClient a context
> manager, so that I can write
>
> with HTTPClient(url) as client:
>     pass

Actually, I overestimated the task:

   class HTTPClient(url):
       def __enter__(self):
           return self
       def __exit__(self, ctx_type, ctx_val, ctx_tb):
           self.close()
       def close(self):
           self._myfile.close()
           self._mysocket.close()

I'll simply ignore the fact that closing a file can fail if you can't 
flush buffers. Now, my error was that I have to somehow invoke the 
file's and socket's enter function in my client's enter function. The 
default for all files and sockets is that they are already open, they 
are not opened in the enter function! That way, the client remains 
usable outside a with context but gives me the desired guarantees inside 
one.

For the case of on-demand allocated stuff, I could write the enter 
function like this:

   def __enter__(self):
       # allocate resources
       f = ... # open file
       s = ... # connect socket
       # attach after completion
       self._myfile = f
       self._mysocket = s

To be extra safe or in more complicated scenarios, I could wrap this in 
a try-except and explicitly close those that were already created, but 
normally I'd expect the garbage collector to do that for me ... or am I 
then implicitly assuming a specific implementation?


Uli



More information about the Python-list mailing list