user721975
user721975

Reputation: 1267

How to unread a line in python

I am new to Python (2.6), and have a situation where I need to un-read a line I just read from a file. Here's basically what I am doing.

  for line in file:
     print line
     file.seek(-len(line),1)
     zz = file.readline()
     print zz

However I notice that "zz" and "line" are not the same. Where am I going wrong?

Thanks.

Upvotes: 8

Views: 4322

Answers (4)

Michael Kent
Michael Kent

Reputation: 1734

Untested. Basically, you want to maintain a lifo cache of 'unread' lines. On each read of a line, if there is something in the cache, you take it out of the cache first. If there's nothing in the cache, read a new line from the file. This is rough, but should get you going.

lineCache = []

def pushLine(line):
    lineCache.append(line)

def nextLine(f):
    while True:
        if lineCache:
            yield lineCache.pop(0)
        line = f.readline()
        if not line:
            break
        yield line
    return

f = open('myfile')

for line in nextLine(f):
    # if we need to 'unread' the line, call pushLine on it.  The next call to nextLine will
    # return the that same 'unread' line.
    if some_condition_that_warrants_unreading_a_line:
        pushLine(line)
        continue
    # handle line that was read.

Upvotes: 2

jfs
jfs

Reputation: 414285

You can combine the iteration over lines with a .seek() operation:

for i, line in enumerate(iter(f.readline, ''), 1):
    print i, line,
    if i == 2: # read 2nd line two times
       f.seek(-len(line), os.SEEK_CUR)

If a file contains:

a
b
c

Then the output would be:

1 a
2 b
3 b
4 c

Upvotes: 2

Gustav Larsson
Gustav Larsson

Reputation: 8487

I don't think for line in file: and seek make a good combination. Try something like this:

while True:
    line = file.readline()
    print line
    file.seek(-len(line),1)
    zz = file.readline()
    print zz

    # Make sure this loop ends somehow

Upvotes: 12

David Heffernan
David Heffernan

Reputation: 612993

You simply cannot mix iterators and seek() this way. You should pick one method and stick to it.

Upvotes: 3

Related Questions