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