If you need to process a text file one record at a time, the cleanest way to read a file line by line in Python is a with open() block and a plain for line in f loop.
What trips people up is everything around it: the \n at the end of each line, blank lines, header rows, and files too big for memory.
In this tutorial, I’ll show you how Python read file line by line works with five methods on one small orders file, plus a real memory test and the chunk-reading trap that cuts records in half.
The Sample orders.txt File We’ll Read Line by Line
Every example reads the same file: six March 2026 orders from US customers. I ran the code with Python 3.12.5 on Windows.
order_id,date,customer,state,total
1001,2026-03-02,Rachel Turner,TX,1204.50
1002,2026-03-02,Marcus Hill,CO,875.25
1003,2026-03-03,Jenna Brooks,WA,1530.00
1004,2026-03-03,Tyler Ramirez,MA,990.75
1005,2026-03-04,Olivia Grant,FL,1312.40
1006,2026-03-04,Derek Collins,NV,640.00
Two lines are tricky on purpose: a header row, and a blank line after order 1003. If open() modes and paths are new to you, see how to open a file in Python first.
Method 1: Read a File Line by Line with a for Loop (Recommended)
I use this for almost every file. The file object is an iterator, so you get one line per pass and the whole file is never loaded. Here it skips the header and blank line and totals the orders:
total = 0.0
with open("orders.txt", encoding="utf-8") as f:
header = next(f) # skip the header row
for number, line in enumerate(f, start=2):
line = line.rstrip("\n")
if not line:
print(f"line {number}: blank, skipped")
continue
order_id, date, customer, state, amount = line.split(",")
total += float(amount)
print(f"line {number}: {order_id} {customer:<14} "
f"${float(amount):>9,.2f}")
print(f"Total: ${total:,.2f}")
Output:
line 2: 1001 Rachel Turner $ 1,204.50
line 3: 1002 Marcus Hill $ 875.25
line 4: 1003 Jenna Brooks $ 1,530.00
line 5: blank, skipped
line 6: 1004 Tyler Ramirez $ 990.75
line 7: 1005 Olivia Grant $ 1,312.40
line 8: 1006 Derek Collins $ 640.00
Total: $6,552.90

How does this code work?
with closes the file when the block ends, even after an error; with open in Python explains why. next(f) reads and discards the header line.
enumerate(f, start=2) numbers lines the way a text editor does (see enumerate() in Python). Each line arrives with its \n, so rstrip("\n") removes it, and an empty result means the blank line.
Method 2: Read One Line at a Time with readline()
Use readline() when you want to control when the next line is read. Each call returns one line:
with open("orders.txt", encoding="utf-8") as f:
header = f.readline() # read the header first
while True:
line = f.readline()
if line == "": # "" only at the end of the file
print("End of file reached")
break
if line == "\n": # a blank line is "\n", not ""
print("Blank line read as '\\n', keep going")
continue
print(line.rstrip("\n").split(",")[2])
Output:
Rachel Turner
Marcus Hill
Jenna Brooks
Blank line read as '\n', keep going
Tyler Ramirez
Olivia Grant
Derek Collins
End of file reached

'\n', and the loop stops only at the real end of the file.How does this code work?
At the end of the file, readline() returns an empty string. A blank line returns "\n", which isn’t empty, so the loop keeps going and all six names print.
Important: don’t use while line.strip(): as the test. It stops at the first blank line and silently drops orders 1004 to 1006. More on loop tests in Python while loop conditions.
On Python 3.8+, while (line := f.readline()): reads and tests in one line. To drop a header other ways, see skipping the first line of a file.
Method 3: Read All Lines into a List with readlines() or pathlib
readlines() returns the whole file as a list, one string per line. It’s handy for small files when you need a count or a line by index. pathlib gives a cleaner version:
from pathlib import Path
with open("orders.txt", encoding="utf-8") as f:
lines = f.readlines()
print(len(lines), "lines")
print(repr(lines[1]))
print(repr(lines[4]))
clean = Path("orders.txt").read_text(encoding="utf-8").splitlines()
print(repr(clean[1]))
print(len([line for line in clean[1:] if line]), "orders")
Output:
8 lines
'1001,2026-03-02,Rachel Turner,TX,1204.50\n'
'\n'
'1001,2026-03-02,Rachel Turner,TX,1204.50'
6 orders
The list holds 8 lines, each still ending in \n, and the blank line is just '\n'. read_text().splitlines() returns the same lines without endings, and dropping empty strings leaves 6 orders.
How does this code work?
Both load the full file into memory, fine for short files. I prefer splitlines() because the strings come out clean. For one line by number, see reading a specific line from a file.
Need the file as one string or a file in an array instead? Those guides cover it.
Method 4: Read Lines from Several Files with fileinput
fileinput chains files into one loop. Here orders.txt is followed by orders_april.txt (same header, two April orders):
import fileinput
files = ["orders.txt", "orders_april.txt"]
with fileinput.input(files=files, encoding="utf-8") as f:
for line in f:
if fileinput.isfirstline():
print(f"== {fileinput.filename()}")
continue # skip each header
if line.strip():
print(fileinput.filelineno(), line.rstrip())
Output:
== orders.txt
2 1001,2026-03-02,Rachel Turner,TX,1204.50
3 1002,2026-03-02,Marcus Hill,CO,875.25
4 1003,2026-03-03,Jenna Brooks,WA,1530.00
6 1004,2026-03-03,Tyler Ramirez,MA,990.75
7 1005,2026-03-04,Olivia Grant,FL,1312.40
8 1006,2026-03-04,Derek Collins,NV,640.00
== orders_april.txt
2 1007,2026-04-01,Hannah Price,CT,455.10
3 1008,2026-04-02,Caleb Foster,GA,1189.99
Both headers are skipped, and each order shows its line number inside its own file.
How does this code work?
isfirstline() is true on line 1 of every file, and filename() names the current file. encoding needs Python 3.10+. With no files given, it reads standard input; see stdin and stdout in Python.
Method 5: Read a Large File Line by Line with a Generator
When several parts of a program need the same cleaned records, wrap the loop in a generator. You’ll still read one line at a time, but callers get parsed tuples:
def read_orders(path):
"""Yield (order_id, customer, amount) one line at a time."""
with open(path, encoding="utf-8") as f:
next(f) # header
for line in f:
if line := line.strip():
oid, _, customer, _, amount = line.split(",")
yield oid, customer, float(amount)
for oid, customer, amount in read_orders("orders.txt"):
if amount > 1000:
print(f"{oid} {customer:<14} ${amount:,.2f}")
Output:
1001 Rachel Turner $1,204.50
1003 Jenna Brooks $1,530.00
1005 Olivia Grant $1,312.40
The loop prints the three orders over $1,000: 1001, 1003 and 1005.
How does this code work?
yield pauses after each order, so only one line is in memory at a time. My post on yield in Python goes deeper.
How Much Memory Does readlines() Use on a Large File?
I generated a 300,000-line orders file and totaled it with each approach, measuring peak memory with tracemalloc:
import tracemalloc
with open("orders_2026.txt", "w", encoding="utf-8") as f:
for i in range(300_000):
f.write(f"{100000 + i},2026-03-15,TX,{i % 500 + 0.99:.2f}\n")
def total(lines):
return sum(float(line.rsplit(",", 1)[1]) for line in lines)
for name in ("readlines", "for loop"):
tracemalloc.start()
with open("orders_2026.txt", encoding="utf-8") as f:
t = total(f.readlines() if name == "readlines" else f)
peak = tracemalloc.get_traced_memory()[1] / 1_048_576
tracemalloc.stop()
print(f"{name:<10} total ${t:,.2f} peak memory {peak:.2f} MB")
Output:
readlines total $75,147,000.00 peak memory 22.18 MB
for loop total $75,147,000.00 peak memory 0.03 MB

readlines() peaks at tens of megabytes while the for loop needs a tiny fraction of that.Both return $75,147,000.00. readlines() peaked at 22.18 MB because all 300,000 strings sat in one list; the loop peaked at 0.03 MB. For big CSVs, see reading large CSV files in Python.
Why Does Reading a File in Chunks Split Lines?
Some guides use f.read(size). It reads characters, not lines, so records get cut wherever a chunk ends. Here’s the file in 64-character chunks:
with open("orders.txt", encoding="utf-8") as f:
while chunk := f.read(64):
print(repr(chunk))
Output:
'order_id,date,customer,state,total\n1001,2026-03-02,Rachel Turner'
',TX,1204.50\n1002,2026-03-02,Marcus Hill,CO,875.25\n1003,2026-03-0'
'3,Jenna Brooks,WA,1530.00\n\n1004,2026-03-03,Tyler Ramirez,MA,990.'
'75\n1005,2026-03-04,Olivia Grant,FL,1312.40\n1006,2026-03-04,Derek'
' Collins,NV,640.00\n'

The first chunk stops after “Rachel Turner” and the next starts with ,TX,1204.50. You’d have to stitch the pieces back together, which for line in f already does.
Which Method Should You Use to Read a File Line by Line?
| Method | Memory | Best for |
|---|---|---|
for line in f | One line | Almost everything, any size |
readline() | One line | Header first, stopping early |
readlines() / splitlines() | Whole file | Small files, indexing |