nesting context managers

Ian Kelly ian.g.kelly at gmail.com
Tue Dec 20 13:46:40 EST 2011


On Tue, Dec 20, 2011 at 9:56 AM, Ulrich Eckhardt
<ulrich.eckhardt at dominolaser.com> wrote:
> 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?

For full generality, copy the code for the contextlib.nested function
in Python 2.7 or 3.1 and use that.  Don't use contextlib.nested
itself, though, because it's deprecated and does not exist in Python
3.2.

Cheers,
Ian



More information about the Python-list mailing list