On Fri, Apr 9, 2021 at 6:41 AM Ethan Furman <et...@stoneleaf.us> wrote:
>
> On 4/8/21 1:21 PM, Chris Angelico wrote:
> > On Fri, Apr 9, 2021 at 6:16 AM Ethan Furman wrote:
> >> On 4/8/21 11:25 AM, Chris Angelico wrote:
>
> >>> Similar question: What would be the semantics of this?
> >>>
> >>> with contextlib.suppress(BaseException):
> >>>       a = b / c
> >>> except BaseException as e:
> >>>       print(e)
> >>>
> >>> What types of exception could be caught and what types couldn't?
> >>
> >> Well, if every exception is derived from BaseException (they are) and 
> >> contextlib.suppress(BaseException) suppresses all
> >> BaseException-derived exceptions (it does) then the semantics of the above 
> >> are:
> >>
> >> - "a" will be the result of "b / c" if no exception occurs
> >> - otherwise, "a" will be whatever it was before the with-block
> >> - no exception will ever be caught by the except-clause
> >>
> >> Generally speaking, no exception that a context manager handles (i.e. 
> >> suppresses) will ever be available to be caught.
> >
> > What about NameError looking up contextlib, or AttributeError looking
> > up suppress? Will they be caught by that except clause, or not?
>
> Ah, good point -- those two would get caught, as they happen before 
> contextlib.suppress() gets control.
>
> > Thank you for making my point: your assumption is completely the
> > opposite of the OP's, given the same syntactic structure.
>
> The guidance should be:  `try with` behaves exactly as `try/except with a 
> with`, meaning that NameError and
> AttributeError for those two reasons would still be caught.  Yes, it's easy 
> to miss that at first glance, but it's just
> as easy to miss in the traditional try/except layout:
>
> ```python
> try:
>      with contextlib.suppress(BaseException):
>          # do stuff
> except BaseException as e:
>      print(e)
> ```
>
> How many people are going to look at that and think, "oh, NameError and 
> AttributeError can still be caught" ?
>

At least in this form, it's clear that there's a sharp distinction
between the stuff around the outside of the 'with' block and the stuff
inside it.

The semantics, as suggested, give 'with' blocks two distinct
exception-management scopes, which mostly but do not entirely overlap.
It's not a problem to rigorously define the semantics, but as
evidenced here, people's intuitions will vary depending on which
context manager is being used. It's absolutely obvious that the OP's
example should let you catch errors from open(), and equally obvious
that suppressing BaseException should mean that nothing gets caught.
That's the problem here.

As such, I'm -0.5 on this. It's a kinda nice feature, but all it
really offers is one less indentation level, and the semantics are too
confusing.

ChrisA
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/3GGA3QLJCBJVRDCYU2HQS4K5DHLJ65TV/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to