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:
">

(original) (raw)




On Thu, Oct 17, 2013 at 9:06 AM, Barry Warsaw <barry@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