Context Managers (Livehacking Tutorial)

Exception Unsafety

f = open('/etc/passwd', 'br')   # binary!
for line in f:
    if line.find('jfasch') >= 0: # exception!
        print(line)
        break
else:
    print('no')

# won't get here
f.close()
print('file closed')
$ python code/05-manual-file.py
Traceback (most recent call last):
  File "code/05-manual-file.py", line 3, in <module>
    if line.find('jfasch') >= 0:
TypeError: argument should be integer or bytes-like object, not 'str'
  • File object remains open

  • Fix would have to have try ... finally

  • Convoluted

Exception Safety

with open('/etc/passwd') as f:
    for line in f:
        if line.find('jfasch') >= 0:
            print(line)
            break
    else:
        print('no')
$ python code/10-with-file.py
jfasch:x:1000:1000:Joerg Faschingbauer:/home/jfasch:/bin/bash
  1. encapsulate that into context manager, raw __enter__ and __exit__

  2. find more esoteric example. replace print to do coloring?

  3. contextlib.contextmanager

orig_print = print
def prefix_print(*args, **kwargs):
    pfargs = ('prefix',) + args
    orig_print(*pfargs, **kwargs)
print = prefix_print
print('blah')