15

I am reading a file in Python line by line and I need to know which line is the last one while reading,something like this:

 f = open("myfile.txt")
 for line in f:
    if line is lastline:
       #do smth

From the examples I found it involves seeks and complete file readouts to count lines,etc.Can I just detect that the current line is the last one? I tried to go and check for "\n" existence ,but in many cases the last lines is not followed by backslash N.

Sorry if my question is redundant as I didn't find the answer on SO

Community
  • 1
  • 1
Michael IV
  • 11,016
  • 12
  • 92
  • 223
  • @vaultah that's a nice trick but I need to know at the last line that it is the last :) – Michael IV Jul 27 '14 at 16:33
  • so you are only interested in the last line? – Padraic Cunningham Jul 27 '14 at 16:36
  • What are you going to do when you detect it's the last line? Could you just move whatever that is outside of the for loop? – dano Jul 27 '14 at 16:37
  • I use all the lines but I need the last one to append some different stuff before I write it into another file at the same place.I mean,yeah,I can just do it in else: after "for in " but it is really messy.. – Michael IV Jul 27 '14 at 16:42
  • `//` is not the python syntax for commenting. Are you sure you're looking for an answer in python? – inspectorG4dget Jul 27 '14 at 16:42
  • Oops ;) If I were Python programmer I would probably didn't ask this stuff ;) And yes,I am talking about Python. – Michael IV Jul 27 '14 at 16:44
  • After your loop completes, `line` will hold the last line, so you can do whatever processing you like afterwards. – mdurant Jul 27 '14 at 17:01

8 Answers8

9

Check if line is the last line:

with open("in.txt") as f:
    lines = f.readlines()
    last = lines[-1]
    for line in lines:
        if line is last:
            print id(line),id(last)
            # do work on lst line
        else:
            # work on other lines

If you want the second last line use last = lines[-2]

Or simply:

with open("in.txt") as f:
    lines = f.readlines()
    last = lines[-1]
    for line in lines[:-1]:
        # work on all but last line
    # work on last
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
9
import os
path = 'myfile.txt'
size = os.path.getsize(path)
with open(path) as f:
    for line in f:
        size -= len(line)
        if not size:
            print('this is the last line')
            print(line)

Here is an alternative solution, in case it's a really large file, that takes a long time to traverse. The file is read in reverse from end to beginning using seek. It assumes the file is not binary and not compressed and has at least one line break and the very last character is a line break.

import os
path = 'myfile.txt'
size = os.path.getsize(path)
with open(path) as f:
    for i in range(1, size):
        f.seek(size - 1 - i)
        if f.read(1) == '\n':
            print('This is the last line.:')
            last_line = f.read()
            print(last_line)
            break
tommy.carstensen
  • 8,962
  • 15
  • 65
  • 108
  • @ThorbjørnRavnAndersen Good point. It does not. You would need to do `size -= len(line) + 1` instead. Here is an answer on how to identify the type of newline character: https://stackoverflow.com/a/2800981/778533 – tommy.carstensen Dec 22 '17 at 00:50
  • 1
    This is the best answer I've seen in that you don't have to read the file twice, or load the whole thing into memory. Be aware though if you're using `open()` with the `errors` parameter set to something like `'ignore'` or `'backslashescape'` , the read size of each line will not total up to the OS reported file size. – Ryan McGrath Feb 14 '22 at 19:01
  • 1
    Really good solution, worked great for my large dump files where I only need to read the last line. – Jack Hales Feb 20 '22 at 21:56
3
secondLastLine = None
lastLine = None
with open("myfile.txt") as infile:
    secondLastLine, lastLine = infile.readline(), infile.readline()
    for line in infile:
        # do stuff
        secondLastLine = lastLine
        lastLine = line

# do stuff with secondLastLine
inspectorG4dget
  • 110,290
  • 27
  • 149
  • 241
2

One thing you could try is to try to get the next line, and catch the exception if it arises, because AFAIK python iterators don't have inbuilt hasNext method.

hoodakaushal
  • 1,253
  • 2
  • 16
  • 31
2

It's an old question, but if you want to allow empty last lines, this is better:

with open("myfile.txt") as f:
    while True:
        line = f.readline()
        # do smth
        if line[-1:] != '\n':
            # do smth with the last line
            break

or more readable:

with open("myfile.txt") as f:
    while True:
        line = f.readline()
        # do smth
        if not line.endswith('\n'):
            # do smth with the last line
            break
1

You could use the itertools pairwise recipe;

with open('myfile.txt') as infile:
    a,b = itertools.tee(infile)
    next(b, None)
    pairs = zip(a,b)
    lastPair = None
    for lastPair in pairs:
        pass
secondLastLine = lastPair[0]
# do stuff with secondLastLine
inspectorG4dget
  • 110,290
  • 27
  • 149
  • 241
0

just check the output of f.readline(), it should be empty string when you have no more lines in the file.

Alberto.

AlbertoAndreotti
  • 478
  • 4
  • 13
0

Maybe this may help someone

fp = open("somefile.txt", "r")
temp = fp.readline()

while True:
    print(temp)
    # other stuff
    
    temp = fp.readline()
    if not temp:
        print("last")
        # other last line logic
        break

fp.close()