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 <rep...@bugs.python.org> <http://bugs.python.org/issue23227> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com