Non Blocking

If you are on linux (as windows does not support calling select on files) you can use the subprocess module along with the select module.

import time
import subprocess
import select

f = subprocess.Popen(['tail','-F',filename],\
        stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p = select.poll()
p.register(f.stdout)

while True:
    if p.poll(1):
        print f.stdout.readline()
    time.sleep(1)

This polls the output pipe for new data and prints it when it is available. Normally the time.sleep(1) and print f.stdout.readline() would be replaced with useful code.

Blocking

You can use the subprocess module without the extra select module calls.

import subprocess
f = subprocess.Popen(['tail','-F',filename],\
        stdout=subprocess.PIPE,stderr=subprocess.PIPE)
while True:
    line = f.stdout.readline()
    print line

This will also print new lines as they are added, but it will block until the tail program is closed, probably with f.kill().

Answer from Matt on Stack Overflow
🌐
Pandas
pandas.pydata.org › docs › reference › api › pandas.DataFrame.tail.html
pandas.DataFrame.tail — pandas 3.0.2 documentation
DataFrame.tail(n=5)[source]# Return the last n rows. This function returns last n rows from the object based on position. It is useful for quickly verifying data, for example, after sorting or appending rows. For negative values of n, this function returns all rows except the first |n| rows, ...
🌐
W3Schools
w3schools.com › python › pandas › ref_df_tail.asp
Pandas DataFrame tail() Method
The tail() method returns the last 5 rows if a number is not specified.
🌐
Codecademy
codecademy.com › docs › python:pandas › dataframe › .tail()
Python:Pandas | DataFrame | .tail() | Codecademy
July 8, 2024 - In Pandas, .tail() is a method that returns the last n rows of a DataFrame. By default, it returns the last 5 rows, but the number of rows can be adjusted by passing an integer argument to the method.
Top answer
1 of 14
83

Non Blocking

If you are on linux (as windows does not support calling select on files) you can use the subprocess module along with the select module.

import time
import subprocess
import select

f = subprocess.Popen(['tail','-F',filename],\
        stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p = select.poll()
p.register(f.stdout)

while True:
    if p.poll(1):
        print f.stdout.readline()
    time.sleep(1)

This polls the output pipe for new data and prints it when it is available. Normally the time.sleep(1) and print f.stdout.readline() would be replaced with useful code.

Blocking

You can use the subprocess module without the extra select module calls.

import subprocess
f = subprocess.Popen(['tail','-F',filename],\
        stdout=subprocess.PIPE,stderr=subprocess.PIPE)
while True:
    line = f.stdout.readline()
    print line

This will also print new lines as they are added, but it will block until the tail program is closed, probably with f.kill().

2 of 14
57

Using the sh module (pip install sh):

from sh import tail
# runs forever
for line in tail("-f", "/var/log/some_log_file.log", _iter=True):
    print(line)

[update]

Since sh.tail with _iter=True is a generator, you can:

import sh
tail = sh.tail("-f", "/var/log/some_log_file.log", _iter=True)

Then you can "getNewData" with:

new_data = tail.next()

Note that if the tail buffer is empty, it will block until there is more data (from your question it is not clear what you want to do in this case).

[update]

This works if you replace -f with -F, but in Python it would be locking. I'd be more interested in having a function I could call to get new data when I want it, if that's possible. – Eli

A container generator placing the tail call inside a while True loop and catching eventual I/O exceptions will have almost the same effect of -F.

def tail_F(some_file):
    while True:
        try:
            for line in sh.tail("-f", some_file, _iter=True):
                yield line
        except sh.ErrorReturnCode_1:
            yield None

If the file becomes inaccessible, the generator will return None. However it still blocks until there is new data if the file is accessible. It remains unclear for me what you want to do in this case.

Raymond Hettinger approach seems pretty good:

def tail_F(some_file):
    first_call = True
    while True:
        try:
            with open(some_file) as input:
                if first_call:
                    input.seek(0, 2)
                    first_call = False
                latest_data = input.read()
                while True:
                    if '\n' not in latest_data:
                        latest_data += input.read()
                        if '\n' not in latest_data:
                            yield ''
                            if not os.path.isfile(some_file):
                                break
                            continue
                    latest_lines = latest_data.split('\n')
                    if latest_data[-1] != '\n':
                        latest_data = latest_lines[-1]
                    else:
                        latest_data = input.read()
                    for line in latest_lines[:-1]:
                        yield line + '\n'
        except IOError:
            yield ''

This generator will return '' if the file becomes inaccessible or if there is no new data.

[update]

The second to last answer circles around to the top of the file it seems whenever it runs out of data. – Eli

I think the second will output the last ten lines whenever the tail process ends, which with -f is whenever there is an I/O error. The tail --follow --retry behavior is not far from this for most cases I can think of in unix-like environments.

Perhaps if you update your question to explain what is your real goal (the reason why you want to mimic tail --retry), you will get a better answer.

The last answer does not actually follow the tail and merely reads what's available at run time. – Eli

Of course, tail will display the last 10 lines by default... You can position the file pointer at the end of the file using file.seek, I will left a proper implementation as an exercise to the reader.

IMHO the file.read() approach is far more elegant than a subprocess based solution.

🌐
GitHub
gist.github.com › amitsaha › 5990310
Simple implementation of the tail command in Python · GitHub
#! /usr/bin/env python # -*- coding: utf-8 -*- # # >> # Blake VandeMerwe, LiveViewTech # << import os import io import asyncio from functools import partial from typing import AsyncIterator LINE_BUFFER = 1 async def tail( filename: str, last_lines: int = 10, non_exist_max_secs: float = 30.0, fp_poll_secs: float = 0.125 ) -> AsyncIterator[str]: """Continuously tail a file pointer yielding one line at a time.""" async def wait_exists() -> bool: """Wait for a file to exist, the return statement reflects whether or not the file existed when the timeout limits were reached.""" bail_at: float = time
🌐
GitHub
github.com › kasun › python-tail
GitHub - kasun/python-tail: Unix tail follow implementation in python · GitHub
python setup.py install · import tail # Create a tail instance t = tail.Tail('file-to-be-followed') # Register a callback function to be called when a new line is found in the followed file. # If no callback function is registerd, new lines would be printed to standard out.
Starred by 297 users
Forked by 107 users
Languages   Python
🌐
w3resource
w3resource.com › pandas › series › series-tail.php
Pandas Series: tail() function - w3resource
This function returns last n rows from the object based on position. It is useful for quickly verifying data, for example, after sorting or appending rows. Syntax: Series.tail(self, n=5) Parameters: Returns: type of caller The last n rows of ...
🌐
GitHub
github.com › kasun › python-tail › blob › master › tail.py
python-tail/tail.py at master · kasun/python-tail
Python-Tail - Unix tail follow implementation in Python. ... ''' Do a tail follow. If a callback function is registered it is called with every new line.
Author   kasun
Find elsewhere
🌐
GeeksforGeeks
geeksforgeeks.org › python-pandas-dataframe-series-tail-method
Pandas Dataframe/Series.tail() method - Python - GeeksforGeeks
March 22, 2025 - Python is a popular language for data analysis because it has many useful libraries. One of these libraries is Pandas, which makes working with data easier. The .tail() method in Pandas helps us see the last n rows of a DataFrame or Series.
🌐
TutorialsPoint
tutorialspoint.com › article › python-pandas-how-to-use-pandas-dataframe-tail-function
Python Pandas – How to use Pandas DataFrame tail( ) function
May 27, 2024 - The Pandas DataFrame tail() function returns the last n rows of a DataFrame. This is particularly useful when combined with filtering operations to examine the bottom portion of your filtered data.
🌐
Educative
educative.io › answers › what-are-head-and-tail-functions-in-pandas
What are head and tail functions in pandas?
The tail function in Python displays the last five rows of the dataframe by default. It takes in a single parameter: the number of rows.
🌐
PyPI
pypi.org › project › tailer
tailer
JavaScript is disabled in your browser. Please enable JavaScript to proceed · A required part of this site couldn’t load. This may be due to a browser extension, network issues, or browser settings. Please check your connection, disable any ad blockers, or try using a different browser
🌐
Pandas
pandas.pydata.org › pandas-docs › stable › reference › api › pandas.DataFrame.tail.html
pandas.DataFrame.tail — pandas 3.0.1 documentation
DataFrame.tail(n=5)[source]# Return the last n rows. This function returns last n rows from the object based on position. It is useful for quickly verifying data, for example, after sorting or appending rows. For negative values of n, this function returns all rows except the first |n| rows, ...
🌐
Analytics Vidhya
analyticsvidhya.com › home › head () and tail () functions explained with examples and codes
Head () and Tail () Functions Explained with Examples and Codes
June 11, 2025 - Analysts can check column names, data types, and the data itself by displaying the initial records. The head() function is available in many programming languages, including Python and R. The tail() function offers a rapid view of the final few rows of a dataset, just like the head() does.
🌐
Lethain
lethain.com › tailing-in-python
Tailing in Python | Irrational Exuberance
May 16, 2010 - def readlines_then_tail(fin): "Iterate through lines and then tail for further lines." while True: line = fin.readline() if line: yield line else: tail(fin)
🌐
Javatpoint
javatpoint.com › head-and-tail-function-in-python
Head and Tail Function in Python - Javatpoint
Head and Tail Function in Python with tutorial, tkinter, button, overview, canvas, frame, environment set-up, first python program, etc.
🌐
PyPI
pypi.org › project › pythontail
pythontail · PyPI
for the example1.py, generate the minimum of 2 fake log files This will create two fake_n.log files in ~/log/fake_n.log that can be tailed · python pythontail/pythontail.py -f ~/log/fake_1.log ~/log/fake_2.log
      » pip install pythontail
    
Published   Feb 21, 2024
Version   0.9
🌐
TutorialsPoint
tutorialspoint.com › python_pandas › python_pandas_basic_functionality.htm
Python Pandas - Basic Functionality
import pandas as pd import numpy as np # Create a Series with random numbers s = pd.Series(np.random.randn(10)) print("Series:") print(s) # Using basic methods print("First 5 elements of the Series:\n", s.head()) print("\nLast 3 elements of the Series:\n", s.tail(3)) print("\nDescriptive statistics of the Series:\n", s.describe())