Phoenix
Phoenix

Reputation: 41

Beginner : python len() closes file?

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.

The original code from the book works perfectly and I copy below - so that I can show the difference:

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()

What I decided to do, is to avoid having a variable in_file AND indata so I did some changes in lines 9-10, 12 and 19 and wrote the following 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()

My problem is:

1) As written the amended 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

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

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

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?

I would appreciate the help, because this drives me a bit nuts :)

Upvotes: 4

Views: 187

Answers (1)

ASGM
ASGM

Reputation: 11391

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

indata = in_file.read()

The reason is that when you call in_file.read(), 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 in_file.read() the second time, python starts where the bookmark was left - at the end, with no more pages left to read.

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.

in_file.seek(0)

Upvotes: 2

Related Questions