[Python-ideas] with-except-finally blocks

Kale Kundert kale at thekunderts.net
Thu Apr 16 08:39:37 CEST 2015


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...')

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



More information about the Python-ideas mailing list