Path: csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!weretis.net!feeder1.news.weretis.net!feeder.erje.net!newsfeed.xs4all.nl!newsfeed5.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.001 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'context': 0.04; 'socket': 0.04; 'stuff,': 0.07; 'python': 0.08; 'client:': 0.09; 'created,': 0.09; 'deprecated': 0.09; 'flush': 0.09; 'garbage': 0.09; 'sockets': 0.09; 'am,': 0.12; '2.7': 0.13; '3.2.': 0.16; 'allocate': 0.16; 'close(self):': 0.16; 'eckhardt': 0.16; 'task:': 0.16; '\xa0def': 0.16; 'cc:addr:python-list': 0.16; 'this:': 0.16; 'wrote:': 0.18; 'wrap': 0.18; 'cc:no real name:2**0': 0.20; 'cheers,': 0.20; 'dec': 0.22; 'assume': 0.22; 'header:In-Reply- To:1': 0.22; 'filing': 0.23; 'itself,': 0.23; 'somehow': 0.23; 'cc:2**0': 0.24; 'received:74.125.82.174': 0.24; 'code': 0.25; 'ignore': 0.26; 'expect': 0.26; 'function': 0.27; 'fact': 0.27; 'message-id:@mail.gmail.com': 0.28; 'allocated': 0.29; 'assuming': 0.29; 'explicitly': 0.29; 'cc:addr:python.org': 0.29; 'error': 0.29; 'class': 0.29; 'closing': 0.30; "client's": 0.30; 'implicitly': 0.30; 'invoke': 0.30; 'remains': 0.30; 'usable': 0.30; "i'll": 0.31; 'does': 0.32; 'attach': 0.32; 'tue,': 0.32; "can't": 0.32; 'normally': 0.34; 'function.': 0.34; 'received:74.125.82': 0.35; 'file': 0.36; '...': 0.36; 'http': 0.37; 'but': 0.37; 'received:74.125': 0.37; 'received:google.com': 0.37; 'skip:_ 10': 0.37; 'could': 0.37; 'open': 0.38; 'fail': 0.39; 'skip:\xa0 10': 0.39; 'client': 0.39; "i'd": 0.39; 'files': 0.39; "it's": 0.40; '8bit%:8': 0.40; 'more': 0.61; '2011': 0.61; 'connect': 0.62; 'full': 0.62; 'manager,': 0.62; 'opened': 0.64; 'safe': 0.70; 'completion': 0.82; 'on-demand': 0.91; 'open,': 0.91 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type:content-transfer-encoding; bh=wCO3jl+XngncUAL0wqmo86nbUF94mnNxZ1Dg79Zpw7Q=; b=n3vrlOucl0SD9Q8Adg5gEaOu4RhR9NnVAzjHPMkXJfhqNlNm1gcIOLeinMukOG0fm3 zTUgFBWKBOVfXoH2SR07bUhQiJD4e/KBqBlu9M5wsQD5efLcS/rB2uSpqkNvMJm/zfsq XeXrB1BWwEFAz+q5/scA4YA4bJtvoxfAxFeOI= MIME-Version: 1.0 In-Reply-To: References: From: Ian Kelly Date: Tue, 20 Dec 2011 11:46:40 -0700 Subject: Re: nesting context managers To: Ulrich Eckhardt Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Cc: python-list@python.org X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 59 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1324406832 news.xs4all.nl 6890 [2001:888:2000:d::a6]:40030 X-Complaints-To: abuse@xs4all.nl Xref: x330-a1.tempe.blueboxinc.net comp.lang.python:17599 On Tue, Dec 20, 2011 at 9:56 AM, Ulrich Eckhardt 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: >> =A0 =A0pass > > > Actually, I overestimated the task: > > =A0class HTTPClient(url): > =A0 =A0 =A0def __enter__(self): > =A0 =A0 =A0 =A0 =A0return self > =A0 =A0 =A0def __exit__(self, ctx_type, ctx_val, ctx_tb): > =A0 =A0 =A0 =A0 =A0self.close() > =A0 =A0 =A0def close(self): > =A0 =A0 =A0 =A0 =A0self._myfile.close() > =A0 =A0 =A0 =A0 =A0self._mysocket.close() > > I'll simply ignore the fact that closing a file can fail if you can't flu= sh > 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 al= l > files and sockets is that they are already open, they are not opened in t= he > enter function! That way, the client remains usable outside a with contex= t > but gives me the desired guarantees inside one. > > For the case of on-demand allocated stuff, I could write the enter functi= on > like this: > > =A0def __enter__(self): > =A0 =A0 =A0# allocate resources > =A0 =A0 =A0f =3D ... # open file > =A0 =A0 =A0s =3D ... # connect socket > =A0 =A0 =A0# attach after completion > =A0 =A0 =A0self._myfile =3D f > =A0 =A0 =A0self._mysocket =3D 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 t= hen > 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