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):
try:
for line in f:
logging.warning(line.strip())
yield line
finally:
logging.warning('closing')
f.close()
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
False
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()
WARNING:root:closing
>>> f.closed
True
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@python
components: Documentation, Interpreter Core
messages: 233903
nosy: docs@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 <[email protected]>
<http://bugs.python.org/issue23227>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com