DmitriiGangan
DmitriiGangan

Reputation: 13

Python: Writing to file using for loop

Using this Python code I get printed lines of file in UPPERCASE but file remains unchanged (lowercase.)

def open_f():
    while True:
        fname=raw_input("Enter filename:")
        if fname != "done":
            try:
                fhand=open(fname, "r+")
                break
            except:
                print "WRONG!!!"
                continue

        else: exit()
    return fhand

fhand=open_f()
for line in fhand:
    ss=line.upper().strip()
    print ss
    fhand.write(ss)
fhand.close()

Can you suggest please why files remain unaffected?

Upvotes: 1

Views: 1888

Answers (4)

tripleee
tripleee

Reputation: 189377

Like already alluded to in comments, you cannot successively read from and write to the same file -- the first write will truncate the file, so you cannot read anything more from the handle at that point.

Fortunately, the fileinput module offers a convenient inplace mode which works exactly like you want.

import fileinput
for line in fileinput.input(somefilename, inplace=True):
    print(line.upper().strip())

Upvotes: 0

Noctis Skytower
Noctis Skytower

Reputation: 21991

This program should do as you requested and allows for modifying the file as it is being read. Each line is read, converted to uppercase, and then written back to the source file. Since it runs on a line-by-line basis, the most extra memory it should need would be related to the length of the longest line.

Example 1

def main():
    with get_file('Enter filename: ') as file:
        while True:
            position = file.tell()              # remember beginning of line
            line = file.readline()              # get the next available line
            if not line:                        # check if at end of the file
                break                           # program is finished at EOF
            file.seek(position)                 # go back to the line's start
            file.write(line.upper())            # write the line in uppercase


def get_file(prompt):
    while True:
        try:                                    # run and catch any error
            return open(input(prompt), 'r+t')   # r+t = read, write, text
        except EOFError:                        # see if user if finished
            raise SystemExit()                  # exit the program if so
        except OSError as error:                # check for file problems
            print(error)                        # report operation errors

if __name__ == '__main__':
    main()

The following is similar to what you see up above but works in binary mode instead of text mode. Instead of operating on lines, it processes the file in chunks based on the given BUFFER_SIZE and can operate more efficiently. The code under the main loop may replace the code in the loop if you wish for the program to check that it is operating correctly. The assert statements check some assumptions.

Example 2

BUFFER_SIZE = 1 << 20


def main():
    with get_file('Enter filename: ') as file:
        while True:
            position = file.tell()
            buffer = file.read(BUFFER_SIZE)
            if not buffer:
                return
            file.seek(position)
            file.write(buffer.upper())
        # The following code will not run but can replace the code in the loop.
        start = file.tell()
        buffer = file.read(BUFFER_SIZE)
        if not buffer:
            return
        stop = file.tell()
        assert file.seek(start) == start
        assert file.write(buffer.upper()) == len(buffer)
        assert file.tell() == stop


def get_file(prompt):
    while True:
        try:
            return open(input(prompt), 'r+b')
        except EOFError:
            raise SystemExit()
        except OSError as error:
            print(error)

if __name__ == '__main__':
    main()

Upvotes: 0

Clever Programmer
Clever Programmer

Reputation: 606

Code:

def file_reader(read_from_file):
    with open(read_from_file, 'r') as f:
        return f.read()

def file_writer(read_from_file, write_to_file):
    with open(write_to_file, 'w') as f:
        f.write(file_reader(read_from_file))

Usage:

  1. Create a file named example.txt with the following content:

Hi my name is
Dmitrii
Gangan.

  1. Create an empty file called file_to_be_written_to.txt

  2. Add this as the last line file_writer("example.txt", "file_to_be_written_to.txt") of your .py python file.

  3. python <your_python_script.py> from the terminal.

NOTE: They all must be in the same folder.

Result:

file_to_be_written_to.txt:

Hi my name is
Dmitrii
Gangan.

Upvotes: 3

Quinn
Quinn

Reputation: 4504

I suggest the following approach:

1) Read/close the file, return the filename and content

2) Create a new file with above filename, and content with UPPERCASE

def open_f():
    while True:
        fname=raw_input("Enter filename:")
        if fname != "done":
            try:
                with open(fname, "r+") as fhand:
                    ss = fhand.read()
                break
            except:
                print "WRONG!!!"
                continue

        else: exit()
    return fname, ss

fname, ss =open_f()
with open(fname, "w+") as fhand:
    fhand.write(ss.upper())

Upvotes: 0

Related Questions