To read a specific line from a text file in Python, loop over the file with enumerate(f, start=1) and return the line when the counter matches. It streams the file, so size doesn’t matter. linecache.getline(path, n) is the one-call option:
import linecache
line = linecache.getline("orders.log", 3) # 3rd line, '' if missing
To check the behaviour of each method, including what happens past the end of the file, I ran them all on Python 3.12.5.
You’ll see the enumerate function, a side-by-side of readlines, islice and linecache, picking several lines or a range, the linecache caching trap, and how each copes with a million-line log.
Read a specific line from a file with enumerate()
Line numbers people use start at 1, so pass start=1. The function stops reading as soon as it finds the line and returns None if the file is shorter:
def read_line(path, line_number):
"""Return line `line_number` (1 = first line) without the newline, or None."""
with open(path, encoding="utf-8") as f:
for number, line in enumerate(f, start=1):
if number == line_number:
return line.rstrip("\n")
return None
print(read_line("orders.log", 3))
print(read_line("orders.log", 8))
print(read_line("orders.log", 50))
Output:
2026-10-06 09:00:03 INFO order 1003 shipped to Boston
2026-10-06 09:00:08 INFO order 1008 shipped to Austin
None

rstrip("\n") removes the line break but keeps other spaces. For the line-by-line pattern in general, see reading a file line by line in Python.
readlines(), islice() and linecache compared
Three other approaches give the same line 5, but they behave very differently when the line doesn’t exist:
import linecache
from itertools import islice
path, n = "orders.log", 5
with open(path, encoding="utf-8") as f:
print("readlines:", f.readlines()[n - 1].rstrip())
with open(path, encoding="utf-8") as f:
print("islice: ", next(islice(f, n - 1, None)).rstrip())
print("linecache:", linecache.getline(path, n).rstrip())
# asking for a line that doesn't exist
with open(path, encoding="utf-8") as f:
print("islice 50: ", repr(next(islice(f, 49, None), None)))
print("linecache 50:", repr(linecache.getline(path, 50)))
with open(path, encoding="utf-8") as f:
try:
f.readlines()[49]
except IndexError as err:
print("readlines 50: IndexError:", err)
Output:
readlines: 2026-10-06 09:00:05 INFO order 1005 shipped to Reno
islice: 2026-10-06 09:00:05 INFO order 1005 shipped to Reno
linecache: 2026-10-06 09:00:05 INFO order 1005 shipped to Reno
islice 50: None
linecache 50: ''
readlines 50: IndexError: list index out of range

linecache returning '' can hide a bug, because a real blank line also prints as nothing. When I only need the start or end of a file, I use the dedicated recipes for reading the first line of a file.
How do I read multiple specific lines from a file?
Put the line numbers in a set and collect matches in one pass. For a continuous range, islice() is simpler, but remember its start is 0-based:
from itertools import islice
wanted = {2, 4, 7}
with open("orders.log", encoding="utf-8") as f:
picked = {n: line.rstrip() for n, line in enumerate(f, start=1) if n in wanted}
for n, line in picked.items():
print(n, line)
print("--- lines 3 to 5 ---")
with open("orders.log", encoding="utf-8") as f:
for line in islice(f, 2, 5): # 0-based start, end not included
print(line.rstrip())
Output:
2 2026-10-06 09:00:02 INFO order 1002 shipped to Seattle
4 2026-10-06 09:00:04 INFO order 1004 shipped to Tampa
7 2026-10-06 09:00:07 INFO order 1007 shipped to Mesa
--- lines 3 to 5 ---
2026-10-06 09:00:03 INFO order 1003 shipped to Boston
2026-10-06 09:00:04 INFO order 1004 shipped to Tampa
2026-10-06 09:00:05 INFO order 1005 shipped to Reno

To skip header rows before processing, see skipping the first line in a file.
Why does linecache return an old line?
linecache keeps the whole file in memory after the first call. If the file changes, you’ll keep getting the old content until you call checkcache():
import linecache
from pathlib import Path
print(linecache.getline("orders.log", 1).rstrip())
Path("orders.log").write_text("2026-10-06 10:00:00 INFO file was rotated\n", encoding="utf-8")
print(linecache.getline("orders.log", 1).rstrip()) # still the cached copy
linecache.checkcache("orders.log")
print(linecache.getline("orders.log", 1).rstrip()) # fresh read
Output:
2026-10-06 09:00:01 INFO order 1001 shipped to Denver
2026-10-06 09:00:01 INFO order 1001 shipped to Denver
2026-10-06 10:00:00 INFO file was rotated
That makes it a poor fit for log files that are still being written. To change a line rather than read it, see replacing a specific line in a file.
Read a specific line from a large file
Here’s line 750,000 of a million-line log, read four ways, with time and peak memory measured by tracemalloc:
import linecache
import time
import tracemalloc
from itertools import islice
from pathlib import Path
with open("big.log", "w", encoding="utf-8") as f:
for i in range(1_000_000):
f.write(f"2026-10-06 INFO request {i} from 10.0.{i % 256}.{i % 200} took {i % 900} ms\n")
print(f"big.log: {Path('big.log').stat().st_size / 1_048_576:.1f} MB, 1,000,000 lines")
def run(label, fn):
tracemalloc.start()
start = time.perf_counter()
line = fn()
took = time.perf_counter() - start
peak = tracemalloc.get_traced_memory()[1] / 1_048_576
tracemalloc.stop()
print(f"{label:<10} {took * 1000:8.1f} ms peak {peak:7.1f} MB -> {line.split()[3]}")
n = 750_000
run("readlines", lambda: open("big.log", encoding="utf-8").readlines()[n - 1])
run("enumerate", lambda: next(l for i, l in enumerate(open("big.log", encoding="utf-8"), 1) if i == n))
run("islice", lambda: next(islice(open("big.log", encoding="utf-8"), n - 1, None)))
run("linecache", lambda: linecache.getline("big.log", n))
Output:
big.log: 58.0 MB, 1,000,000 lines
readlines 541.6 ms peak 104.2 MB -> 749999
enumerate 499.6 ms peak 0.0 MB -> 749999
islice 299.9 ms peak 0.0 MB -> 749999
linecache 672.9 ms peak 104.2 MB -> 749999

Timings change from run to run, but the memory gap is what matters: readlines() and linecache load every line. For the last lines of a big file, use reading the last line of a file instead.
Which method should you use?
| Method | Missing line | Memory | Best for |
|---|---|---|---|
enumerate(f, 1) loop | Your choice (None) | One line | Most cases |
islice(f, n-1, None) | None with a default | One line | Ranges, big files |
linecache.getline() | '' | Whole file, cached | Repeated lookups in a static file |
f.readlines()[n-1] | IndexError | Whole file | Small files you already loaded |
More file-reading recipes worth bookmarking:
- Read a file into an array in Python
- Count words in a file with Python
- Remove newlines from a string in Python
- Read a binary file in Python
Frequently asked questions
How do I read a specific line from a file in Python?
Loop with for n, line in enumerate(f, start=1) and return the line when n matches, or use linecache.getline(path, n).
Are line numbers 0-based or 1-based?
linecache and enumerate(..., start=1) are 1-based. List indexes and islice() are 0-based, so use n - 1.
What happens if the line number is past the end of the file?
readlines() raises IndexError, linecache returns an empty string, and islice returns the default you pass to next().
How do I read lines 10 to 20 of a file?
Use islice(f, 9, 20), which yields lines 10 through 20.
What is the fastest way to read one line of a huge file?
Stream it with islice() or an enumerate loop. Avoid readlines(), which loads the whole file.
Where is linecache documented?
See the linecache module in the Python docs.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn