[Python-ideas] With clauses for generator expressions

Andrew Barnert abarnert at yahoo.com
Thu Nov 15 04:44:44 CET 2012


First, I realize that people regularly propose with expressions. This is not the 
same thing.

The problem with the with statement is not that it can't be postfixed 
perl-style, or used in expressions. The problem is that it can't be used with 
generator expressions.

Here's the suggestion:

    upperlines = (lines.upper() for line in file with open('foo', 'r') as file)

This would be equivalent to:

    def foo():
        with open('foo', 'r') as file:
            for line in file:
                yield line.upper()
    upperlines = foo()

The motivation is that there is no way to write this properly using a with 
statement and a generator expression—in fact, the only way to get this right is 
with the generator function above. And almost nobody ever gets it right, even 
when you push them in the right direction (although occasionally they write a 
complex class that has the same effect).

That's why we still have tons of code like this lying around:

    upperlines = (lines.upper() for line in open('foo', 'r'))

Everyone knows that this only works with CPython, and isn't even quite right 
there, and yet people write it anyway, because there's no good alternative.

The with clause is inherently part of the generator expression, because the 
scope has to be dynamic. The file has to be closed when iteration finishes, not 
when creating the generator finishes (or when the generator is cleaned up—which 
is closer, but still wrong).

That's why a general-purpose "with expression" wouldn't actually help here; in 
fact, it would just make generator expressions with with clauses harder to 
parse. A with expression would have to be statically scoped to be general.

For more details, see this:

http://stupidpythonideas.blogspot.com/2012/11/with-clauses-for-generator-expressions.html



More information about the Python-ideas mailing list