hayaliv

hayaliv / Hi! Python / Level 1

Text and the `with` statement

Read text one line at a time, and let with close the file for you.

Hi! Python · Level 1: Files and data · Checked against the Python 3.12 documentation · Updated 2026-10-17

Think of it like this

Reading a text file is like reading a letter one line at a time. A with block is like borrowing a book from a library desk: when you walk away from the desk, the book goes back on the shelf.

Where the analogy stops being true. A library book is returned by you or a librarian, but with closes the file by itself, even if an error happens inside the block.

What to know

Example

import io

raw = "I can meet Tuesday.\nNot interested, thanks.\n\nCall me at 5pm.\n"
with io.StringIO(raw) as f:
    for number, line in enumerate(f, start=1):
        text = line.rstrip("\n")
        print(number, repr(text))
print(f.closed)

It prints:

1 'I can meet Tuesday.'
2 'Not interested, thanks.'
3 ''
4 'Call me at 5pm.'
True

Predict, then check

1. What does this print?

import io

print(list(io.StringIO("a\nb\n")))
Show the answer
['a\n', 'b\n']

Looping over the stream gives lines, and each line still ends with a newline character.

2. What does this print?

import io

f = io.StringIO("one\ntwo\n")
first = f.readline()
rest = list(f)
print(repr(first), rest)
Show the answer
'one\n' ['two\n']

The loop carries on from where readline stopped, so only the second line is left.

3. What does this print?

import io

with io.StringIO("hi") as f:
    data = f.read()
try:
    f.read()
except ValueError:
    print("closed", data)
Show the answer
closed hi

After the with block the stream is closed, so reading again raises ValueError.

Try it

Write count_nonblank_lines(f). It receives a file-like object and returns how many lines contain something other than whitespace.

def count_nonblank_lines(f):
    return 0
Show a solution
def count_nonblank_lines(f):
    return sum(1 for line in f if line.strip())

Common mistake

A line read from a file still ends with a newline, so comparing it to a plain label such as "yes" is False until you strip it (see predict item 1).

In a small-language-model project

In a fine-tuning project you often start with a plain text file of raw replies, one per line. Reading it with with and an explicit encoding, then skipping blank lines, is the first cleaning step. Replies in Albanian, or any language with letters outside ASCII such as ë and ç, are a good reason to name the encoding yourself.

Sources

Each quote below appears word for word on the cited page of the official Python documentation (version 3.12).

Step through this lesson in the Hi! Python desktop

← ComprehensionsJSON →