Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #17601
| References | <ash6s8-qj5.ln1@satorlaser.homedns.org> <nbr6s8-n86.ln1@satorlaser.homedns.org> <CALwzidnGdNhfCAiGSAzU6bASCRdof_VGZAL_MCzGx0+dFUKb4A@mail.gmail.com> |
|---|---|
| From | Ian Kelly <ian.g.kelly@gmail.com> |
| Date | 2011-12-20 11:55 -0700 |
| Subject | Re: nesting context managers |
| Newsgroups | comp.lang.python |
| Message-ID | <mailman.3875.1324407391.27778.python-list@python.org> (permalink) |
On Tue, Dec 20, 2011 at 11:46 AM, Ian Kelly <ian.g.kelly@gmail.com> wrote:
> On Tue, Dec 20, 2011 at 9:56 AM, Ulrich Eckhardt
> <ulrich.eckhardt@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.
Also note that in versions that do support the nested with syntax, you
can do something like:
class HTTPClient(url):
@contextlib.contextmanager
def _contextmanager(file, socket):
with file, socket:
yield
def __enter__(self):
self._cm = self._contextmanager(self._myfile, self._mysocket)
return self._cm.__enter__()
def __exit__(self, exc_type, exc_value, traceback):
try:
return self._cm.__exit__(exc_type, exc_value, traceback)
finally:
del self._cm
Cheers,
Ian
Back to comp.lang.python | Previous | Next — Previous in thread | Find similar | Unroll thread
nesting context managers Ulrich Eckhardt <ulrich.eckhardt@dominolaser.com> - 2011-12-20 15:15 +0100
Re: nesting context managers Rami Chowdhury <rami.chowdhury@gmail.com> - 2011-12-20 16:25 +0000
Re: nesting context managers Ulrich Eckhardt <ulrich.eckhardt@dominolaser.com> - 2011-12-20 17:56 +0100
Re: nesting context managers Rami Chowdhury <rami.chowdhury@gmail.com> - 2011-12-20 17:46 +0000
Re: nesting context managers Ian Kelly <ian.g.kelly@gmail.com> - 2011-12-20 11:46 -0700
Re: nesting context managers Ethan Furman <ethan@stoneleaf.us> - 2011-12-20 10:02 -0800
Re: nesting context managers Ian Kelly <ian.g.kelly@gmail.com> - 2011-12-20 11:55 -0700
csiph-web