0

I could not find any official recommended indentation for the following idiom (straight from http://effbot.org/zone/python-with-statement.htm):

with open(path) as f:
    data = f.read()
    do something with data

or:

with open(path) as f:
    data = f.read()
do something with data

IMHO, the first version is better at showing the scope, but the latter may prevent an excessive indentation. Is choosing one of those just a matter of taste? Or is there any authoritative source or established tradition to follow?


As a side note, I cannot help but think that with is quite apart from the other block-constructing Python keywords. For instance, there is no question about choosing between:

if condition:
    do something
    do something different

or:

if condition:
    do something
do something different

Since they do... well, something different.

5
  • 1
    If you (have to) worry about excessive indentation (because of do something consisting of many lines) you should probably put the loop and the something into separate functions/methods, and make data a (return) parameter. Voilà, the scope is well defined then.
    – Murphy
    Feb 23 '17 at 9:02
  • @Murphy Probably, yes. Note that "do something with data" is taken literally (there is no do loop in Python). I've taken this example from: effbot.org/zone/python-with-statement.htm
    – Aristide
    Feb 23 '17 at 9:08
  • 15
    Indentation doesn't show the scope, it defines it. Version 1 isn't any better at showing the scope, it just needlessly extends it. The fact that data originally came from a file doesn't mean that you need to keep the file opened while you process data. Feb 23 '17 at 9:09
  • Your last paragraph is completely wrong. The with block behaves the same as the if block, your first two samples are not doing quite the same thing.
    – jonrsharpe
    Feb 23 '17 at 11:35
  • If you are really only opening a file and doing a single read without catching any exceptions, you can just do data = open(path).read(). This is equivalent to your second example. Feb 24 '17 at 5:22
17

I always use the second approach because it ensures that I don't hold the resource (file in your case) open longer than necessary.

1
  • 1
    This is definitely the answer. Made the mistake in a SE answer this very day, by the way. Also, the with statement itself is NOT failsafe, it can throw file exceptions that you need to properly handle, something that is very easy to forget.
    – Arthur Hv
    Feb 23 '17 at 9:44
7

In python indentation affect how the program works.

with open(path) as f:
    data = f.read()
    do something with data

means: open path in f, read in data, do stuff with data, close f

and

with open(path) as f:
    data = f.read()
do something with data

means: open path in f, read in data, close f, do stuff with data. (I like this more, as i prefer to close files as soon as possible)

So they are not strictly equivalent: indentation in the magical world of python matters as much as curly braces in C-like languages.

1
  • Indeed, thanks. To make the difference appear, one could try to re-open the file in the 3rd line. Which is not quite what I meant with "do something with data", but I cannot find a better example.
    – Aristide
    Feb 23 '17 at 12:30
1

I don't have enough reputation to comment. I agree that it saves resources to close the file first and then process the data. However, I think the first approach (that keeps the file open) is more preferable if you have a large file. See How can I read large text files in Python, line by line, without loading it into memory? on Stack Overflow.

4
  • Not quite. f.read() is reading the whole file into memory. To save memory usage, you could implement a loop and use f.readline() (or f.read(100)), but you have to be able to do something with that chunk (and then throw it away before loading the next chunk) or all you've done is read the whole thing into memory, but slower. Mar 5 '20 at 12:02
  • "the second approach (that keeps the file open)" ? It's the first approach that keeps the file open. Mar 5 '20 at 14:15
  • @ChrisMurray; you don't need to call .read() or .readline(), you can more easily just for line in file:. Mar 6 '20 at 14:56
  • @ChrisMurray Thanks for pointing it out. I think it is a typo.
    – Z. L.
    Apr 23 '20 at 18:29

Not the answer you're looking for? Browse other questions tagged or ask your own question.