Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #98617

Re: Keeping context-manager object alive through function calls

Path csiph.com!fu-berlin.de!uni-berlin.de!not-for-mail
From Chris Angelico <rosuav@gmail.com>
Newsgroups comp.lang.python
Subject Re: Keeping context-manager object alive through function calls
Date Wed, 11 Nov 2015 09:53:43 +1100
Lines 52
Message-ID <mailman.223.1447196026.16136.python-list@python.org> (permalink)
References <CAB_tDZw-3aMqzdwD728NNOxJsYYLXTZVdqQpErY1bz=Pz_LNkA@mail.gmail.com>
Mime-Version 1.0
Content-Type text/plain; charset=UTF-8
X-Trace news.uni-berlin.de 4izVfuK246Wp5MnwIaSdVQYw/I0lNsqpds7b23yfA3fA==
Return-Path <rosuav@gmail.com>
X-Original-To python-list@python.org
Delivered-To python-list@mail.python.org
X-Spam-Status OK 0.010
X-Spam-Evidence '*H*': 0.98; '*S*': 0.00; 'context': 0.05; 'cc:addr :python-list': 0.09; '*is*': 0.09; 'modes': 0.09; 'output': 0.13; 'def': 0.13; 'wed,': 0.15; 'conn': 0.16; 'conn)': 0.16; 'conn):': 0.16; 'contextlib': 0.16; 'depart': 0.16; 'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16; 'received:209.85.213.176': 0.16; 'received:io': 0.16; 'received:psf.io': 0.16; 'subject:alive': 0.16; 'subject:object': 0.16; 'wrote:': 0.16; '2015': 0.20; 'cc:2**0': 0.20; 'cc:addr:python.org': 0.20; 'am,': 0.23; 'defined': 0.23; 'this:': 0.23; 'second': 0.24; 'import': 0.24; 'header:In-Reply-To:1': 0.24; 'separate': 0.27; 'question': 0.27; 'message-id:@mail.gmail.com': 0.27; 'data,': 0.27; 'yield': 0.27; 'device': 0.28; 'be:': 0.29; 'forces': 0.29; 'guarantees': 0.29; 'other,': 0.29; 'another': 0.32; 'handle': 0.34; 'skip:d 20': 0.34; 'gets': 0.35; 'received:google.com': 0.35; 'done': 0.35; 'clear': 0.35; 'nov': 0.35; 'but': 0.36; 'there': 0.36; 'received:209.85': 0.36; 'subject:: ': 0.37; 'two': 0.37; 'turn': 0.37; 'received:209.85.213': 0.37; 'received:209': 0.38; 'names': 0.38; 'whatever': 0.39; 'subject:-': 0.39; 'build': 0.40; 'easy': 0.60; 'your': 0.60; 'managers': 0.63; 'benefit': 0.66; 'here': 0.66; 'connection.': 0.76; '9:36': 0.84; 'abandon': 0.84; 'chrisa': 0.84; 'gen': 0.84; 'pablo': 0.84; 'subject:calls': 0.84; 'to:none': 0.91
DKIM-Signature v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:cc :content-type; bh=7/YAlJE6dkqp3MhX4Jybcv+yJyq3qj4V1xd/v9nENC0=; b=XQtkBv9nf/JlAnfQXR7UmFc1hrVZkydRZbCd7ciaPQv63KhH8UqNpg41rl18S8iQpu pH8BTCNAZ6KOr3ugEzkQHoevPTE3DCiLeDhagROJpXv7MM9uJKc/LUlpvPfBgMcwkOtV mhxCjAk6L1CSOtEbWuUFLCt1/2k07pYUteNwZ1MvJpCug9rAWGILFHIWCNwWEWprujar N+On3XiBoozT0UT7NHgGYLWP8n7IhFL7ZfKllHfK9ZhdSB/wtuycV4EmLzolEfTwsyIr vd4udXDwsQd/eCQkAp3VRgEUie4JoosBKsUUn98EDgpyFeZK6IkNpyPQLEIG4JSOueg8 U7KA==
X-Received by 10.50.83.104 with SMTP id p8mr29380563igy.13.1447196023733; Tue, 10 Nov 2015 14:53:43 -0800 (PST)
In-Reply-To <CAB_tDZw-3aMqzdwD728NNOxJsYYLXTZVdqQpErY1bz=Pz_LNkA@mail.gmail.com>
X-BeenThere python-list@python.org
X-Mailman-Version 2.1.20+
Precedence list
List-Id General discussion list for the Python programming language <python-list.python.org>
List-Unsubscribe <https://mail.python.org/mailman/options/python-list>, <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive <http://mail.python.org/pipermail/python-list/>
List-Post <mailto:python-list@python.org>
List-Help <mailto:python-list-request@python.org?subject=help>
List-Subscribe <https://mail.python.org/mailman/listinfo/python-list>, <mailto:python-list-request@python.org?subject=subscribe>
Xref csiph.com comp.lang.python:98617

Show key headers only | View raw


On Wed, Nov 11, 2015 at 9:36 AM, Pablo Lucena <plucena24@gmail.com> wrote:
> And calling it as such:
>
> def do_more_stuff(device):
>     gen = do_stuff(device, return_handle=True)
>     data, conn = next(gen)
>     output = conn.send_command("show users")
>     #process output...
>     return processed_output

The first question needs to be: When *is* conn to be closed? What
you've done here is abandon all of the benefit of the context manager,
because it's no longer clear when you're done with the connection.
Here's an alternative: Turn your generator into another context
manager.

from contextlib import contextmanager

@contextmanager
def do_stuff(device):
    with manager(device) as conn:
        output = conn.send_command("show ip route")
        #process output...
        yield (processed_output, conn)

def do_stuff_now(device):
    with do_stuff(device) as (out, conn):
        return out

This forces you to separate the return_handle=True and
return_handle=False modes into two separate functions, but since one
is defined in terms of the other, you don't have a massive maintenance
burden. (Backward compatibility might have you call the first one
do_stuff_with_handle and the second one gets the name do_stuff. Or
whatever names make sense. Handwave.)

So now you can use do_stuff_now() the way you were using do_stuff(),
and if you want to keep using the handle afterward, you use it like
this:

def do_more_stuff(device):
    with do_stuff(device) as (data, conn):
        output = conn.send_command("show users")
        #process output...
        return processed_output

This guarantees that the device will be closed as you depart do_more_stuff.

There are other ways, but this is an easy way to build context
managers on top of context managers.

ChrisA

Back to comp.lang.python | Previous | Next | Find similar | Unroll thread


Thread

Re: Keeping context-manager object alive through function calls Chris Angelico <rosuav@gmail.com> - 2015-11-11 09:53 +1100

csiph-web