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
>>> df.tail() animal 4 monkey 5 parrot 6 shark 7 whale 8 zebra · Viewing the last n lines (three in this case) >>> df.tail(3) animal 6 shark 7 whale 8 zebra · For negative values of n · >>> df.tail(-3) animal 3 lion 4 monkey 5 parrot 6 shark 7 whale 8 zebra ·
🌐
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. ... Note: The column names will also be returned, in addition to the specified rows.
Discussions

tail -f equivalent in python?

to avoid reading every X, monitor the file instead http://pythonhosted.org/watchdog/

you shouldn't have to re-open the file, just read until you get an emptystring, then go back to monitoring, then read more lines from the file object

More on reddit.com
🌐 r/learnpython
18
17
January 10, 2014
Does python support Tail-Recursion
Python doesn't optimise tail-calls, so no. At least not right now. That said you're generally better-off with iterative solutions anyway unless the problem in question is either too complex to be effectively solved iteratively, or the recursion depth limit cannot reasonably ever be reached (eg. when traversing the filesystem, you're not going to run into a situation in practice where there would be directory trees much deeper than 30 nodes). For instance, there exists a really great iterative solution for the Fibonacci sequence: def fib(): a, b = 0, 1 while True: yield a a, b = b, a+b More on reddit.com
🌐 r/learnpython
7
2
October 6, 2021
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.

🌐
GeeksforGeeks
geeksforgeeks.org › pandas › python-pandas-dataframe-series-tail-method
Pandas Dataframe/Series.tail() method - Python - GeeksforGeeks
July 26, 2025 - We will use the tail() method to retrieve the last few rows of a DataFrame. This provides a quick preview of the dataset’s structure and contents. By default, the method returns and stores the last 5 rows of the DataFrame in a new variable ...
🌐
Reddit
reddit.com › r/learnpython › tail -f equivalent in python?
r/learnpython on Reddit: tail -f equivalent in python?
January 10, 2014 -

I have a text file that's being written to constantly and I need to use the data that's being added to the end of the file in real time.

On *nix systems, I use tail -f for log files that works well.. but say I want to do this within python, what's the best method of doing this?

Files will be read only by python, and open / actively being written to by another process as python reads.

(and no, I can't hook into the other process directly, I must read a txt file in real time...)

Ideally I'd like to avoid doing a 'read' on the file every few milliseconds to detect new lines... hence looking for something like tail...

thanks!

EDIT: PS. I did google this before, but I found solutions that were OS specific.. I'm hoping there's some library or built in feature that is platform agnostic so I can port this script.

🌐
Chrispenner
chrispenner.ca › posts › python-tail-recursion
Tail Recursion In Python
July 26, 2016 - There's a few reasons for this, the simplest of which is just that python is built more around the idea of iteration than recursion. But hey, I don't really care if this is something we should or shouldn't be doing, I'm just curious if we can! Let's see if we can make it happen. # factorial.py from tail_recursion import tail_recursive, recurse # Normal recursion depth maxes out at 980, this one works indefinitely @tail_recursive def factorial(n, accumulator=1): if n == 0: return accumulator recurse(n-1, accumulator=accumulator*n)
Find elsewhere
🌐
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.
🌐
GitHub
github.com › kasun › python-tail
GitHub - kasun/python-tail: Unix tail follow implementation in python · GitHub
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. t.register_callback(callback_function) # Follow the file with 5 seconds as sleep time between iterations.
Starred by 297 users
Forked by 107 users
Languages   Python
🌐
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 - The head() function in pandas displays the top rows of a DataFrame, while the tail() function shows the bottom rows. Both functions are used to get a quick overview of the data’s structure and contents, making them essential tools for data exploration and analysis in Python.
🌐
Python.org
discuss.python.org › ideas
Explicit tail calls - Ideas - Discussions on Python.org
July 11, 2025 - There are good reasons for why Python doesn’t have automatic tail recursion elimination. (Implementation is difficult; developers need guarantees in order for it to make sense to write recursive algorithms.) But what about explicit tail calls? Compilers nowadays allow annotations for explicit ...
🌐
Reverberate
blog.reverberate.org › 2025 › 02 › 10 › tail-call-updates.html
A Tail Calling Interpreter For Python (And Other Updates)
February 10, 2025 - I’m happy to see that this seems to have come true for Python. Congratulations to Ken on this accomplishment. In 2022-2024, Haoran Xu published a series of articles and papers about an ambitious and experimental effort to automatically generate interpreters and JIT compilers from a description of the language semantics. This project is called Deegen, and Haoran used it to build LuaJIT Remake, an experimental reimplementation of the famous LuaJIT. Deegen uses the tail call pattern for its interpreters, arguing that this the best way to get the compiler to generate good code.
🌐
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.
🌐
Python Forum
python-forum.io › thread-41861.html
reading a file like the unix tail -f command does
March 29, 2024 - i want to have my script read a file that another process may or may not have written more to that file extending its size. in unix, the 'tail -f' command does this once it has reached EOF. i want my script to read this way. imagine the script is ...
🌐
The Code Library
ayada.dev › posts › implement-tail-command-in-python
The Code Library | Implement tail command in Python
January 12, 2021 - As a bonus, I have used argparse to handle the input from cli. Let’s look at the implementation of this program. import argparse import queue def tail(filename, n): q = queue.Queue() size = 0 with open(filename) as fh: for line in fh: q.put(line.strip()) if size >= n: q.get() else: size += 1 for i in range(size): print(q.get()) if __name__ == '__main__': parser = argparse.ArgumentParser(description='Print last n lines from a file.') parser.add_argument('file', type=str, help='File to read from') parser.add_argument('-n', type=int, default=10, help='The last n lines to be printed') args = parser.parse_args() tail(args.file, args.n)
🌐
PYnative
pynative.com › home › python › pandas › pandas dataframe head, tail, at, iat
Pandas DataFrame head, tail, at, iat
March 9, 2023 - import pandas as pd student_dict = {'Name': ['Joe', 'Nat', 'Harry','Jack','Jose',"Jill","Rose"], 'Age': [20, 21, 19,17,18,19,17], 'Marks': [85.10, 77.80, 91.54,72,87.9,90,72]} # create DataFrame from dict student_df = pd.DataFrame(student_dict) # display the bottom 5 rows bottomRows = student_df.tail() print(bottomRows)Code language: Python (python) Run · Output · Name Age Marks 2 Harry 19 91.54 3 Jack 17 72.00 4 Jose 18 87.90 5 Jill 19 90.00 6 Rose 17 72.00 · When we want to see a smaller section of data from the bottom of the DataFrame, we can use the function DataFrame.tail() and pass a parameter as the number of rows to display from the bottom. Example · In the below example, after we apply the DataFrame.tail(3) function, we see that only the last 3 rows of the DataFrame are displayed.
🌐
w3resource
w3resource.com › pandas › series › series-tail.php
Pandas Series: tail() function - w3resource
Python-Pandas Code: import numpy as np import pandas as pd df = pd.DataFrame({'animal':['dog', 'bee', 'cat', 'lion', 'monkey', 'tiger', 'fox', 'wolf', 'zebra']}) df.tail() Output: animal 4 monkey 5 tiger 6 fox 7 wolf 8 zebra · Example - Viewing the last n lines (three in this case): Python-Pandas Code: import numpy as np import pandas as pd df = pd.DataFrame({'animal':['dog', 'bee', 'cat', 'lion', 'monkey', 'tiger', 'fox', 'wolf', 'zebra']}) df.tail(3) Output: animal 6 fox 7 wolf 8 zebra ·
🌐
GeeksforGeeks
geeksforgeeks.org › python › select-first-or-last-n-rows-in-a-dataframe-using-head-and-tail-method-in-python-pandas
Select first or last N rows in a Dataframe using head() and tail() method in Python-Pandas - GeeksforGeeks
July 15, 2025 - Syntax: Dataframe.tail(n) Parameters: (optional) n is integer value, number of rows to be returned. Return: Dataframe with bottom n rows . Example 1: Python3 · # Show bottom 5 rows of the dataframe details.tail() Output: Example 2: Python3 · # Show bottom 3 rows of the dataframe details.tail(3) Output: Example 3: Python3 ·
🌐
Made of Bugs
blog.nelhage.com › post › cpython-tail-call
Performance of the Python 3.14 tail-call interpreter - Made of Bugs
March 9, 2025 - Because all of those python binaries compute the same values when run, our current tools are essentially unable to talk about the distinctions between them in a coherent way. This confusion is one way in which I think the tail-calling interpreter (and the compiler features behind it) represent a genuine, and useful, advance in the state of the art.