Python for Humans · Draft v0.4 · Oct 27, 2026 · Draft position: chapter 5 · Follow Keeping Things Together, reuse the familiar panel and collections, and scale list operations to Shakespeare.

Reading a File

Text Files & Strings

You should already know
Variables and strings (chapter 1); decisions (chapter 2); loops (chapter 3); lists and the Python panel (chapter 4).
You'll build
All of Shakespeare in the Python panel, and an answer to how many times “love” appears.
You'll be able to
Read a file into a string, measure and count text, ignore capitalization in a search, and split text into words.
You need
This page. Python runs in the panel beside it; installing Python on your own computer comes in chapter 9.

From Stories to Real Text

Our adventure used words we typed ourselves. Now let's ask questions about a whole collection of stories. How often does Shakespeare mention love? Which words does he use most? Later, can we use those words to generate a strange new story?

We'll use Shakespeare because the same text is available to everyone. You don't need to have read it. We'll start with the shared file so we can compare results. Later, you'll load your own files; for now, you can also experiment with short strings you type yourself.

Back to the Python Panel

In Keeping Things Together, you used the panel to explore a small collection. Now we'll use the same approach with a whole book: load it once, then ask questions one at a time.

On a small screen, click Python to open the panel. Wait until Python is ready, then type the commands after each >>> and press Enter. Don't type the prompt or the answers shown underneath.

Here's a familiar check before we begin:

>>> supplies = ['torch', 'map', 'pizza']
>>> len(supplies)
3

If you restarted Python or opened a new page, values from your previous session won't be available. We'll create everything we need here. Keep using the same panel throughout this chapter.

Read the Text

A file keeps information after a program ends. I've put a plain-text file called shakespeare.txt in the browser's Python environment, so there's nothing to download yet.

Type this command into the panel and press Enter:

>>> text = open('shakespeare.txt').read()

open() opens the named file; .read() reads its contents into one string. We give that string the name text so we can use it again.

You won't see an answer yet. Just as with supplies, we've assigned a value to a name. This time, the string contains all of Shakespeare instead of a greeting.

There's a lot packed into that line. You can refer back to it whenever you need it; you don't have to memorize it now. We'll return to opening and closing files when we work with files on your own computer.

Keep using the same panel for the commands below. You don't need to read the file again before each question: text is still available.

How Big Is It?

Before you run this next command, guess how many characters the file contains. Thousands? Millions?

>>> len(text)
5378702

len() is short for length. For a string, it counts characters, including spaces, punctuation and line breaks. This file has more than five million of them.

Try the same function with a small string where you can check the answer yourself:

>>> len('Hello!')
6

Now type a len() command for your own name, with quotation marks around it. Predict the result first. Then try a name with a space in it. Does Python count the space?

You've already used len(supplies) to count items in a list. With a string, len() counts characters instead. The value we give it determines what we're measuring.

How Often Does Shakespeare Say “love”?

We could read the file and count by hand. Let's ask Python instead.

>>> text.count('love')
2989

The dot introduces an ability that belongs to the string. text.count('love') means: count how many times the text 'love' occurs inside text.

The name for an ability like this is a method. You'll meet others shortly. For now, notice the shape: the value we're working with, a dot, the method's name, then parentheses containing anything it needs.

Try a different search. Type a command to count 'death', 'king', or a word you choose. You can use the Up arrow and change just the text between the quotation marks.

Before trying the next command, predict whether changing the capital letter will affect the answer:

>>> text.count('Love')
182

Python treats 'love' and 'Love' as different strings, just as it treated 'yes' and 'Yes' differently in our pizza program.

Count Without Worrying About Capitals

What if we want to count love regardless of capitalization?

Strings have another method, lower(), which produces a lowercase version. Let's try it on something small first:

>>> line = 'Love, LOVE, love!'
>>> lowercase_line = line.lower()
>>> lowercase_line
'love, love, love!'
>>> line
'Love, LOVE, love!'

There are no arguments between the parentheses: lower() doesn't need any extra information. It produces a new string. The original line hasn't changed.

Now do the same with Shakespeare, then count in the lowercase version:

>>> lowercase_text = text.lower()
>>> lowercase_text.count('love')
3201
>>> # Your turn: Count 'romeo' in lowercase_text. Then count it in text.
>>> # Why might the results differ? Keep the search itself lowercase so
>>> # it matches the version we made.

We've separated the job into two steps: make a lowercase string, then search it. text still refers to the original version.

You may see the two operations written together:

>>> text.lower().count('love')
3201

Read it from left to right: make a lowercase version of text, then count 'love' in that result. It gives the same answer. You can keep using the two-step version while you get comfortable with this notation.

Is That Really a Word Count?

We've got a number, but what exactly did we count?

Try a small example before answering:

>>> sample = 'love glove lovely'
>>> sample.count('love')
3

count() searches for matching text wherever it occurs. The letters love appear in all three words, so all three contribute to the answer.

Now type text.count('glove') and text.count('lovely') into the panel. Those matches are already included in our original count of 'love'.

Our program ran successfully, but the number doesn't answer quite the question we meant to ask. To count whole words, we need a way to separate the text into words first.

From Text to Words

Strings have a method for that, too. split() separates text at whitespace, such as spaces and line breaks.

Let's use the small sample again:

>>> sample_words = sample.split()
>>> sample_words
['love', 'glove', 'lovely']
>>> len(sample_words)
3

Those square brackets should look familiar: split() gives us a list. Instead of one long string, we have a collection of three strings, each holding one word. You already know how to work with a collection like this.

Type a sentence of your own, give it a name, then use .split() on it. What happens to a comma or full stop attached to a word? Try it before reading on.

split() separates at whitespace; it doesn't remove punctuation. That's another detail we'll have to consider before trusting a word count.

Now split Shakespeare and ask how many pieces we have:

>>> words = text.split()
>>> len(words)
966506

Almost a million! len() works on a list too: it counts its items, rather than the characters in a string.

Let's use the list operations you already know:

>>> words[0]
'The'
>>> words[-1]
'eBooks.'
>>> words.count('love')
1364
>>> # Your turn: Inspect another word by its position, then use
>>> # words.count() to count an exact word of your choosing. Compare it
>>> # with text.count() for the same search. Can you explain why the
>>> # answers might differ?

That's a different answer from counting inside the original string. words.count('love') counts list items equal to 'love', so it leaves out 'glove' and 'lovely'. But it also misses 'Love' and 'love,'. We've improved the question without solving every detail yet.

We could repeat this for each word. But to count every different word, we'll need a way to keep a separate total for each one. That's where dictionaries come in.

Your Turn

Predict the Count

# Each Run starts fresh.
# Write down both answers before running this. What does
# capitalization change?
# Write your prediction below before running.
# After the first run, edit the code and predict again.

line = 'To be, or not to be'
print(line.count('be'))
print(line.count('Be'))

Predict the Relationship

# Each Run starts fresh.
# You won't guess the exact numbers. Predict this instead: is the
# third number bigger than, smaller than, or equal to the first two
# added together? Could other capitalizations change the answer? Run
# it to find out what happens with this particular search.
# Write your prediction below before running.
# After the first run, edit the code and predict again.

text = open('shakespeare.txt').read()
print(text.count('Romeo'))
print(text.count('ROMEO'))
lowercase_text = text.lower()
print(lowercase_text.count('romeo'))

Find the Missing Piece

# Fix the file-reading line.
# Run it and use the last error line as a clue.
# It should print the character count.
# Each Run starts fresh.

text = open('shakespeare.txt').read
print(len(text))

It Runs, but Is It Right?

# Count Romeo regardless of capitalization.
# Fix this using the two-step lowercase approach.
# Does that also solve the whole-word problem?
# Each Run starts fresh.

text = open('shakespeare.txt').read()
print('Romeo is mentioned', text.count('romeo'), 'times')

Ask Three Questions

Use the panel to count three searches of your own choosing. Type each command yourself. Before running it, predict which result will be largest.

Decide whether capitalization matters for your questions, then use either text or lowercase_text. Write down one reason your counts might not mean exactly what they first appear to mean. For example, could your search occur inside another word?

The file also includes a Gutenberg header and license, so these counts include some text Shakespeare didn't write. Real data often needs more preparation than we expect.

Ask a Precise Question

Choose one command you don't fully understand. Write what you expected, what Python showed, and the question you'd ask someone about the difference. Include the command so they can try it themselves.

What I've Learned

Add one sentence to your notes about the difference between counting matching letters and counting whole words. Include a small example that demonstrates the difference.

Optional: Find a Passage

You can go straight to Keeping Count from here. This exploration introduces two more tools for looking inside text; neither is needed to finish the main lesson.

find() tells us where a match begins. Python counts character positions starting at zero. If it can't find the text, it returns -1.

>>> line = 'To be, or not to be'
>>> line.find('be')
3
>>> line.find('Be')
-1

Try finding another word in that short string. Count the characters, including spaces, to check the answer.

For a big string, a position helps us locate a passage:

>>> text.find('wherefore art thou')
3962377
>>> text[3962353:3962402]
'JULIET.\nO Romeo, Romeo, wherefore art thou Romeo?'

The square brackets with a colon take a slice, a portion of the string. The first number is the starting position; the second is where to stop, without including that character. Here we start 24 characters before the match to include the beginning of Juliet's line.

To practice with smaller numbers, type text[:72]. Leaving out the starting position means start at the beginning. Then try text[:300]. Any \n you see represents a line break. Slices work with lists too, using the same start-and-stop notation. You can explore those later; they aren't needed for the next chapter.

What's Next?

You've loaded more than five million characters, asked questions about them, and discovered why a plausible count can still be misleading.

Now we have almost a million separate words. In Keeping Count, we'll keep a count for every different word and explore which ones Shakespeare used most.

© 2026 Python for Humans. All rights reserved.