[Python-ideas] A different kind of context manager

Bruce Leban bruce at leapyear.org
Mon Oct 21 19:21:31 CEST 2013


On Mon, Oct 21, 2013 at 6:55 AM, Kristján Valur Jónsson <
kristjan at ccpgames.com> wrote:

> So, If this is the way people like to think about context managers, like
> writing wrapper functoins, why don‘t we turn them into proper wrapper
> functions?****
>
> <...> The cool thing here though, is that "code" could, for example, be
> run on a different tasklet.  Or a different thread.  Or a different
> universe.
>
Cool, sure. But what are the use cases that need this and can't be done
easily with the existing design?

class NewContextManager(object):
>
  # A context manager that locks a resource, then executes the code only if
> it is not recursing
>   def __init__(self, lock):
>     self.lock = lock
>   def __contextcall__(self, code):
>     with lock:
>       if lock.active:
>         return  # This is where @contextmanager will stop you, you can’t
> skip the ‘yield’
>       lock.active = True
>       try:
>         return code(None) # optionally pass value to the code as in "with
> foo() as X"
>       finally:
>         lock.active = False


You can do that with current context managers:

with lock_once(x) as lock_acquired:
    if lock_acquired:  # was not already locked
        do_stuff_once()

@contextmanager
def lock_once(lock):
    if lock.active:
        yield False
    else:
        lock.active = True
        try:
            yield True
        finally:
            lock.active = False


Note that I'm mimicking your lock/unlock code which of course is not the
proper way to acquire/release a lock, but it gets the idea across. How
would making the code inside the with block a callable improve this? I
think this code is easier to read than yours as the logic of whether or not
the do_stuff_once block is executed is where it belongs -- not hidden in
the context manager. Note that my version also allows me to do this, which
I can't easily do with your context manager:

with lock_once(x) as lock_acquired:
    if lock_acquired:  # was not already locked
        do_stuff_once()
    else:
        log('Lock %r was already acquired', x)
    do_stuff_every_time()



--- Bruce
I'm hiring: http://www.cadencemd.com/info/jobs
Latest blog post: Alice's Puzzle Page http://www.vroospeak.com
Learn how hackers think: http://j.mp/gruyere-security
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20131021/d52e5db0/attachment-0001.html>


More information about the Python-ideas mailing list