HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Reading and Writing in same script

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
scriptreadingsamewritingand

Problem

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')
print text1.read()
text1.close()

# ask user to overwrite the file
print "To overwrite this file, hit ."
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')
print text3.read()
text3.close()

Solution

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.

Now coming to your 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:
        content = f.read()
        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
        # read file's content.
        f.seek(0)
        print f.read()

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)

Code Snippets

from sys import argv


def file_overwrite(filename, n=3):

    with open(filename, 'r+') as f:
        content = f.read()
        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
        # read file's content.
        f.seek(0)
        print f.read()

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)

Context

StackExchange Code Review Q#79303, answer score: 3

Revisions (0)

No revisions yet.