4

I have a function like:

def func(filename):
    with open(filename) as f:
        return [line.split('\t')[0] for line in f]

Is the "with" statement closing the file even when there is a 'sudden' function return? Can I ignore the "with" statement? i.e. is it safe and equivalent (from a memory leak perspective) to do,

def func(filename):
    return [line.split('\t')[0] for line in open(filename)]

?

elyase
  • 39,479
  • 12
  • 112
  • 119

2 Answers2

4

It's safe. The context manager's __exit__ is called even if you return while inside of the context, so the file handle is properly closed.

Here's a simple test:

class ContextTest(object):
    def __enter__(self):
        print('Enter')

    def __exit__(self, type, value, traceback):
        print('Exit')

def test():
    with ContextTest() as foo:
        print('Inside')
        return

When you call test(), you get:

Enter
Inside
Exit
Blender
  • 289,723
  • 53
  • 439
  • 496
  • sorry it is not so clear to me, can I ignore the 'with' and use the second alternative? – elyase May 13 '13 at 01:15
  • @elyase: There's no memory leak in either example, but you aren't explicitly closing the file handle in the second one, which may lead to problems: http://stackoverflow.com/questions/4599980/python-close-file-descriptor-question – Blender May 13 '13 at 01:18
  • great example! You might want to change the `... as test` to something else, it stopped me up a bit since your function name is also test. – monkut May 13 '13 at 01:28
0

Guaranteeing this safety is actually the entire purpose of the with...as... syntax; it replaces try/finally blocks that would otherwise be fairly awkward. So yes, it's guaranteed to be safe, which is why I far prefer with open as f to f = open.

See http://effbot.org/zone/python-with-statement.htm for a good explanation of why the syntax exists and how it works. Note that you can write your own classes with __enter__ and __exit__ methods to really take advantage of this syntax.

Also see the PEP for this feature: http://www.python.org/dev/peps/pep-0343/

Kyle Strand
  • 15,941
  • 8
  • 72
  • 167