[Python-ideas] Fwd: Conditional context manager

Nick Coghlan ncoghlan at gmail.com
Sun Oct 2 03:46:19 EDT 2016


Forwarding to the list, since I took the broken Google Group cc out of
the reply list, but didn't added the proper one.


---------- Forwarded message ----------
From: Nick Coghlan <ncoghlan at gmail.com>
Date: 2 October 2016 at 17:45
Subject: Re: [Python-ideas] Conditional context manager
To: Neil Girdhar <mistersheik at gmail.com>


On 2 October 2016 at 04:07, Neil Girdhar <mistersheik at gmail.com> wrote:
> I'm just throwing this idea out there to get feedback.
>
> Sometimes, I want to conditionally enter a context manager.  This simplest
> (afaik) way of doing that is:
>
>     with ExitStack() as stack:
>         if condition:
>             cm = stack.enter_context(cm_function())
>         suite()
>
> I suggest a more compact notation:
>
>     with cm_function() as cm if condition:
>         suite()

As Chris notes, this is typically going to be better handled by
creating an *un*conditional CM that encapsulates the optionality so
you don't need to worry about it at the point of use.

If you wanted a generic version of that, then the stack creation and
cm creation can be combined into a single context manager:

    @contextmanager
    def optional_cm(condition, cm_factory, *args, **kwds):
        stack = ExitStack()
        cm = None
        with stack:
            if condition:
                cm = stack.enter_context(cm_factory(*args, **kwds))
            yield stack, cm

However, even simpler than both this and Chris's maybe_cm() example is
the plain ExitStack-as-the-null-context-manager function approach
already covered in the contextlib docs:
https://docs.python.org/3/library/contextlib.html#simplifying-support-for-single-optional-context-managers

Applying that approach to this particular pattern looks like:

    def optional_cm(condition, cm_factory, *args, **kwds):
        if condition:
            return cm_factory(*args, **kwds)
        return ExitStack()

Resulting in:

    with optional_cm(condition, cm_function):
        suite()

which is fine for a construct that is uncommon in general, but may be
popular in a particular code base.

Cheers,
Nick.

--
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-ideas mailing list