[New-bugs-announce] [issue23227] Generator's finally block not run if close() called before first iteration

Stephen Drake report at bugs.python.org
Tue Jan 13 08:35:46 CET 2015

New submission from Stephen Drake:

If a generator has its close() method called before any items are requested from it, a finally block in the generator function will not be executed.

I encountered this when wrapping an open file to alter the result of iterating over it.  Using a generator function with a try/finally block seemed like a simple way of acheiving this.  Here's an example that logs each line as it's read:

def logged_lines(f):
        for line in f:
            yield line

If the generator is created and closed immediately, the underlying file-like object is left open:
>>> f = urlopen('https://docs.python.org/')
>>> lines = logged_lines(f)
>>> lines.close()
>>> f.closed

But once the first item is requested from the generator, close() will trigger cleanup:
>>> lines = logged_lines(f)
>>> next(lines)
WARNING:root:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"\n'
>>> lines.close()
>>> f.closed

Having read the documentation for yield expressions, I don't believe this behaviour to be non-conformant - but it still seems like a bit of a gotcha to me.  Should this usage be warned against?

assignee: docs at python
components: Documentation, Interpreter Core
messages: 233903
nosy: docs at python, sjdrake
priority: normal
severity: normal
status: open
title: Generator's finally block not run if close() called before first iteration
type: behavior
versions: Python 2.7, Python 3.4

Python tracker <report at bugs.python.org>

More information about the New-bugs-announce mailing list