with statement and context managers

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed Aug 3 04:15:44 CEST 2011

I'm not greatly experienced with context managers and the with statement, so
I would like to check my logic.

Somebody (doesn't matter who, or where) stated that they frequently use this

spam = MyContextManager(*args)
for ham in my_iter:
    with spam:
         # do stuff

but to me that looks badly wrong. Surely the spam context manager object
will exit after the first iteration, and always raise an exception on the
second? But I don't quite understand context managers enough to be sure.

I've tested it with two examples:

# Simple example using built-in file context manager.

>>> spam = open('aaa')
>>> for ham in range(5):
...     with spam:
...             print ham
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ValueError: I/O operation on closed file

# Slightly more complex example.

>>> from contextlib import closing
>>> import urllib
>>> spam = closing(urllib.urlopen('http://www.python.org'))
>>> for ham in range(5):
...     with spam as page:
...         print ham, sum(len(line) for line in page)
0 18486
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
  File "<stdin>", line 3, in <genexpr>
  File "/usr/local/lib/python2.7/socket.py", line 528, in next
    line = self.readline()
  File "/usr/local/lib/python2.7/socket.py", line 424, in readline
    recv = self._sock.recv
AttributeError: 'NoneType' object has no attribute 'recv'

Am I right to expect that the above idiom cannot work? If not, what sort of
context managers do work as shown?


More information about the Python-list mailing list