[Python-ideas] with-except-finally blocks
Andrew Barnert
abarnert at yahoo.com
Thu Apr 16 09:22:22 CEST 2015
On Apr 15, 2015, at 23:39, Kale Kundert <kale at thekunderts.net> wrote:
>
> Hello everyone,
>
> I'd like to propose a little bit of syntactic sugar: allowing with-blocks to be
> followed by except- and finally-blocks just like try-blocks. For example:
>
> with open('spam.txt') as file:
> print(file.read())
> except IOError:
> print('No spam here...')
> finally:
> print('done.')
>
> This proposed syntax is semantically equivalent to wrapping a with-block within
> a try-block like so:
>
> try:
> with open('spam.txt') as file:
> print(file.read())
> finally:
> print('done.')
> except IOError:
> print('No spam here...')
Why does the finally come before the except? Also, it's still indented with the with, which means you seem to be defining with-except-finally in terms of with-finally, and not defining with-finally at all. Did you mean to have the finally after the except and dedented?
Anyway, I like the idea, but does the grammar work? A with that has an optional except and finally at the same level seems potentially ambiguous. For example:
with spam:
pass
with eggs:
pass
finally:
pass
If you think about it, it's pretty obvious that the finally goes with the second with, not the first. But can the parser tell that? Or a human who's scanning the code rather than thinking carefully about it? Or tools like auto-indenters?
(I think this problem doesn't arise for try, because it must have at least except or finally.)
It should be easy to edit the grammar and build the parser to at least the first part of the question; for the last part, trying to hack up a few different external tools like Emacs python-mode. But for the human question, I'm not sure how to answer it quite so easily...
>
> I see two advantages to the proposed syntax. First and most obviously, it saves
> an extra line and an extra indentation level. One line may not be a big deal,
> but one indentation level can really affect readability. Second and more
> conceptually, it makes sense to think about exception handling in the context of
> a with-block. More often than not, if you're using a with-block, you're
> expecting that something in that block could throw an exception. Usually
> with-blocks are used to make sure resources (e.g. files, database sessions,
> mutexes, etc.) are properly closed before the exception is propogated. But I
> very often want to do some custom clean-up as well (alert the user, etc.).
> Currently that requires wrapping the whole thing in a try-block, but allowing
> with-blocks to behave as try-blocks is a more direct way to express what is meant.
>
> I was curious how often with-blocks are actually wrapped in try-blocks for no
> other purpose than catching exceptions raised in the with-block. So I searched
> through a number of open source projects looking (roughly) for that pattern:
>
> Project with [1] try-with [2]
> ============== ======== ============
> django 230 17
> ipython 541 8
> matplotlib 112 3
> moinmoin 10 0
> numpy 166 1
> pillow/pil 1 0
> pypy 254 4
> scipy 163 2
> sqlalchemy 36 0
> twisted 72 1
> ============== ======== ============
> total 1585 36 (2.27%)
>
> [1]: grep -Po '^\s*with .*:' **/*.py
> [2]: grep -Poz 'try:\s*with .*:' **/*.py
>
> Assuming these projects are representative, about 2% of the with-blocks are
> directly wrapped by try-blocks. That's not a huge proportion, but it clearly
> shows that this pattern is being used "in the wild". Whether or not it's worth
> changing the language for the benefit of 2% of with-blocks is something to
> debate though.
>
> What do people think of this idea?
>
> -Kale Kundert
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
More information about the Python-ideas
mailing list