# Reading and Writing in same script

I just finished working through Exercise 16 of Learn Python The Hard Way. To further study, I wanted to create a script that will read and display a file's contents on screen, and then have the user re-write the file with three lines.

Can my code be written in a much cleaner, pythonic way?

from sys import argv

script, filename = argv

print "The name of the script is: %r" % script

# open txt file and display on screen
text1 = open(filename, 'r')
text1.close()

# ask user to overwrite the file
print "To overwrite this file, hit <enter>."
print "Otherwise, CTRL-C to escape."
raw_input('> ')

# open the txt file again; overwrite it with different data
# have user input new data for each line
text2 = open(filename, 'w')
print "Write three lines to the file."
line1 = raw_input('line 1: ')
line2 = raw_input('line 2: ')
line3 = raw_input('line 3: ')

text2.write('\n'.join([line1, line2, line3, '']))
text2.close()

# read and display reconstructed file
text3 = open(filename, 'r')
text3.close()


First of all I would recommend you to move the code to function so that you can re-use it by importing it in some other module as well.

To differentiate between whether the module has been ran directly or it was imported use the if __name__ = "__main__" condition at the bottom of the code.

• You don't really need to open the file 3 times to do this. With r+ mode this can be done in a single go. Note that good thing about r+ mode is that it also allows us read as well as write to the file.

• Use a with statement to handle a file object, it makes sure that the file object gets closed even when an error occurs.

• Instead of asking the user to hit Enter or CTRL-c ask them for a simply 'yes' or 'no' or may be 'y' or 'n'.

• You're always writing three lines to the file, you can also ask the user for the number of lines they would like to write. Make this a default variable to the function with value 3 if you want them to write 3 lines by default. You can pass this value using another argument to the script: python foo.py file.txt 10. Using this variable you can run a loop and ask the user to enter the lines they would like to write.

• Don't create unnecessary variables like line1, line2 and line3, better use a list and append the lines to it within in a loop.

• Lastly, this is not an issue. But I would recommend that you should use the new-style string formatting over the old printf style string formatting as it is much more powerful and expressive in my opinion.

Code:

from sys import argv

def file_overwrite(filename, n=3):

with open(filename, 'r+') as f:
print content
# ask user to overwrite the file
while True:
feedback = raw_input("Type 'y' to overwrite the file or 'n' to exit: ")
if feedback.lower() == 'y':
# move the file pointer back to the start and then truncate the file
f.seek(0)
f.truncate()
break
elif feedback.lower() == 'n':
# return instantly, another advantage of using a function
return
else:
print "Please enter either 'y' or 'n'."

print 'Write {} lines to the file.'.format(n)
# Loop n times and ask for user input and save it in the list.
lines = []
for line_num in xrange(1, n+1):
line = raw_input('line {}: '.format(line_num))
lines.append(line)

f.write('\n'.join(lines))

# After writing the file pointer is again at the end of the file.
# To read the content again move it back to the start and then
f.seek(0)

if __name__ == '__main__':

# The condition will run only when the user runs this file
# directly.

script, filename = argv[:2]
print "The name of the script is: {!r}.".format(script)
try:
n = int(argv[2])
file_overwrite(filename, n)
except (IndexError, ValueError):
file_overwrite(filename)


For starters, you should only use 1 variable for opening the files. Instead of having text1, text2, and text3, you could have 1 variable called f. Second, you should use:

with open([file],[I.O. mode]) as f:
# COMMANDS ...


An example is:

with open("test.txt","w") as f:
f.write("Hello\n")


Did I mention that the with statement also automatically closes the file once the indent ends?