[Python-Dev] On suppress()'s trail blazing (was Re: cpython: Rename contextlib.ignored() to contextlib.ignore())

Gregory P. Smith greg at krypto.org
Thu Oct 17 22:16:50 CEST 2013


On Thu, Oct 17, 2013 at 9:06 AM, Barry Warsaw <barry at python.org> wrote:

> On Oct 18, 2013, at 01:26 AM, Nick Coghlan wrote:
>
> >By contrast, suppress() and redirect_stdout() are the *first* general
> >purpose context managers added to contextlib since its incarnation in
> >Python 2.5 (although there have been many various domain specific
> >context manager additions elsewhere in the standard library).
>
> There's a fundamental conceptual shift here that's worth exploring more,
> and
> which I think was first identified by RDM.
>
> Until now, context managers were at their heart (at least IMHO) about
> managing
> "resources".  A general resource might be an open file, or it might be a
> database transaction, or even the current working directory.  Context
> managers
> (as expressed elegantly by the `with` statement) are used to ensure that a
> resource acquired for some limited operation is - to Python's best ability
> -
> "released" at the end of that operation, no matter what happens.  E.g. the
> file is closed even if there's a write error, or the current working
> directory
> is restored to its original location.
>
> We need only look at the typical @contextmanager use to see the idiom they
> embody.  As shown in the docstring:
>
> @contextmanager
> def acquire():
>     resource = get_some_resource()
>     try:
>         yield # execute the operation
>     finally:
>         # No matter what happened above...
>         resource.free()
>
> redirect_stdout() conforms to this fine tradition, with the resource being
> sys.stdout.
>
> suppress() breaks the mold, which I think is what is breaking people's
> brains.  It isn't about guaranteeing that a resource is restored to its
> original value after some operation.  It's about short circuiting that
> operation.
>
> Just look at the implementation to see this shift in perspective.  It
> doesn't
> use try/finally, it uses try/except.
>
> So it's important to acknowledge that suppress() is charting new territory
> and
> it will take some exploration and experimentation to get used to, or maybe
> even to decide whether it's a good idea.  It'll be interesting to see
> whether
> this fundamental difference is easily explained, understood, and
> internalized
> and that will go a long way to figuring out whether this is a good idea to
> be
> expanded on in the future.
>

Is this shift to do non-resourcey-things really new?

In 2009 when doing *great things* to the unittest module for the upcoming
Python 2.7 we (michael foord I believe) turned the previous None return
value of assertRaises into a context manager so that it could be used in a
non-resource-management manner similar to:

with self.assertRaises(SomeError) as context:
  state = set_something_up()
  call_offending_thing_on_it(state)

self.assertIn('Bloody Murder!', context.exception.msg)

I thought this was great. As did a bunch of other people in the room. Thus
we have it and happily use it.

It certainly is _not at all_ how I had ever been thinking of context
managers before this feature was added. I had pigeon holed them into
resource management tasks in my mind rather than thinking of them as a
replacement for try..except syntax in common cases.

-gps
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20131017/ef7c82f5/attachment.html>


More information about the Python-Dev mailing list