Beginner : python len() closes file?
<p>I am new to Python and going through the book of Zed. I stumbled upon the following exercise, scope of which is to copy one txt to another.</p>

<p>The original code from the book <em>works perfectly</em> and I copy below - so that I can show the difference:</p>

<pre><code>1 from sys import argv
2 from os.path import exists
3
4 script, from_file, to_file = argv
5
6 print "Copying from %s to %s" % (from_file, to_file)
7
8 # we could do these two on one line too, how?
9 in_file = open(from_file)
10 indata = in_file.read()
11
12 print "The input file is %d bytes long" % len(indata)
13
14 print "Does the output file exist? %r" % exists(to_file)
15 print "Ready, hit RETURN to continue, CTRL- C to abort."
16 raw_input()
17
18 out_file = open(to_file, 'w')
19 out_file.write(indata)
20
21 print "Alright, all done."
22
23 out_file.close()
24 in_file.close()
</code></pre>

<p>What I decided to do, is to avoid having a variable <strong>in_file</strong> AND <strong>indata</strong> so I did some changes in lines 9-10, 12 and 19 and wrote the following code:</p>

<pre><code>from sys import argv
from os.path import exists

script, from_file, to_file = argv

print "Copying from %s to %s" % (from_file, to_file)

# we could do these two on one line too, how?
in_file = open(from_file)


print "The input file is %d bytes long" % len(in_file.read())

print "Does the output file exist? %r" % exists(to_file)
print "Ready, hit RETURN to continue, CTRL- C to abort."
raw_input()

out_file = open(to_file, 'w')
out_file.write(in_file.read())

print "Alright, all done."

out_file.close()
in_file.close()
</code></pre>

<p>My problem is:</p>

<p>1) As written the <strong>amended</strong> code, althouhg it prints correctly the bytes of the in_file.read(), it never copies the text from the from_file to the to_file</p>

<p>2) If in the <strong>amended</strong> I ommit only the line which counts the bytes - so the len() function - then it copies normally the one file to the other . </p>

<p>From my understanding, by evoking the len() function it then closes the in_file.</p>

<p>Is my thought correct? Can I avoid that, by not having to repeat the code in_file = open(from_file)? What else could be the reason?</p>

<p>I would appreciate the help, because this drives me a bit nuts :)</p>

<p>It's actually the act of calling <code>in_file.read()</code> twice that's causing your problem.  You can fix it by assigning the result to a variable, as in the original:</p>

<pre><code>indata = in_file.read()
</code></pre>

<p>The reason is that when you call <code>in_file.read()</code>, you "exhaust" the file.  Think of the file as a book - as the computer reads it, it leaves a bookmark where it leaves off.  So when it's done, the bookmark is left on the last page of the book.  And when you call <code>in_file.read()</code> the second time, python starts where the bookmark was left - at the end, with no more pages left to read.</p>

<p>If you want to avoid creating a variable for some reason, you could "move the bookmark" back to the beginning of the file, as suggested by @WayneWerner in the comments.</p>

<pre><code>in_file.seek(0)
</code></pre>

python