How to read the last line of a file in Python?

Viewed 73198

I have a two requirements .

First Requirement-I want to read the last line of a file and assign the last value to a variable in python.

Second Requirement-

Here is my sample file.

<serviceNameame="demo" wsdlUrl="demo.wsdl" serviceName="demo"/>
<context:property-placeholder location="filename.txt"/>

From this file I want to read the content i.e filename.txt which will be after <context:property-placeholder location= ..And want to assign that value to a variable in python.

8 Answers

A simple solution, which doesn't require storing the entire file in memory (e.g with file.readlines() or an equivalent construct):

with open('filename.txt') as f:
    for line in f:
        pass
    last_line = line

For large files it would be more efficient to seek to the end of the file, and move backwards to find a newline, e.g.:

import os

with open('filename.txt', 'rb') as f:
    try:  # catch OSError in case of a one line file 
        f.seek(-2, os.SEEK_END)
        while f.read(1) != b'\n':
            f.seek(-2, os.SEEK_CUR)
    except OSError:
        f.seek(0)
    last_line = f.readline().decode()

Note that the file has to be opened in binary mode, otherwise, it will be impossible to seek from the end.

Do a size check and seek backwards a certain number of bytes from the end of the file if it contains at least that many bytes:

  with open(filename, 'rb') as myfile:
      if os.path.getsize(filename) > 200:
         myfile.seek(-200, 2)
      line = myfile.readlines()[-1].decode("utf-8")

Opening in binary mode is necessary in python3, which can't do nonzero end-relative seeks. myfile.seek(-200, 2) will place the current file pointer 200 characters before the end of the file (2), then the last line [-1] is taken from readlines() and decoded.

Generalized to read line Nth to last

As many other people have said, for large files, any approach not seeking to the end or otherwise starting at the end of the file is very inefficient. The top answer's seek approach is great though. If anyone else is looking for a solution that reads the nth to last line of the file instead, here is one I wrote. Also very fast and efficient for large files (took under a ms for a 7GB file on the network).

def read_n_to_last_line(filename, n = 1):
    """Returns the nth before last line of a file (n=1 gives last line)"""
    num_newlines = 0
    with open(filename, 'rb') as f:
        try:
            f.seek(-2, os.SEEK_END)    
            while num_newlines < n:
                f.seek(-2, os.SEEK_CUR)
                if f.read(1) == b'\n':
                    num_newlines += 1
        except OSError:
            f.seek(0)
        last_line = f.readline().decode()
    return last_line
Related