Infinite While Loop

Hey again everybody! Long time no see!

Working on text input and outputs right now. My current code is supposed to count each letter that appears in a text document (“lyrics.txt”) and output the number of times each letter appears. The gets stuck in an infinite while loop though, and I’m not entirely sure why. Thoughts?

# This program counts how often each letter appears in Taylor Swift's
# "Enchanted" and prints the count to terminal
#

letterCounts = [0] * 26 # Create 26 lists with initial value of 0

inputFile = open("lyrics.txt", "r")
char = inputFile.read(1)

while char != "" :
    char = char.upper() # Converts the characters to uppercase
    if char >= "A" and char <= "Z" : # Makes sure the character is a letter
        code = ord(char) - ord("A")
        letterCounts[code] = letterCounts[code] + 1
        
for i in range(26) :
    char = chr(i + 65)
    print("%-4s%5d" % (char, letterCounts[i]))

inputFile.close()```

Hi @Rohagan4,

You have only read one byte from the file, and that byte is, of course, not equivalent to an empty string. Therefore, the while loop never terminates. Consider the effect of these lines of code:

char = inputFile.read(1)

while char != "" :

You read one char from the input file, then never read another
one. So your loop just keeps processing that first character over and
over and over and over and over and over and …

Why are you using a while-loop for this? If this is homework, and the
while-loop is required, then that’s fine, it’s a learning exercise. But
in real life, not homework, if you want to read a file and check each
character, use a for-loop not a while-loop.

with open("lyrics.txt", "r") as f:
    for char in f.read():
        # do stuff with the char

Hey Quercus. Thanks for the quick response. I’m still newer to python, but trying to get the hang of it. Since the last line in my text doc is an empty string, I expected that that would trigger the end of the while loop (since the condition would be met). Is this incorrect?

Thanks Steven. It’s not homework, per se, but rather out of a textbook and that’s the example it uses. I’ve typed the code exactly as it is in the text, which makes this especially interesting.

Can you suggest how it might work better with a for loop? Would it be better to add another line

char - inputFile.read(1)

at the end of the While loop? Would that at least fix the infinity loop issue?

This is the only line in the program that reads from the file, and it precedes the while loop:

char = inputFile.read(1)

Consequently, your loop keeps on processing the same letter over and over again forever, which happens to be a "T", in the case of this song. You never reach the end of the file, because you stopped reading it after only one byte.

Correction:

The code is only reading one character, not one byte.

The file is opened in text mode, so it reads in characters, not bytes.
Each character can vary in size between 1 and 4 bytes, depending on the
character itself and the encoding used.

The number of bytes doesn’t really matter.

Hi Ryan,

You could put a line reading the next character at the end of each loop:

while char != '':
    ...
    char = inputFile.read(1)

and that should fix the infinite loop. But it is easier to let Python do
the book-keeping.

If I were to do this, I would read one line of text at a time, rather
than one character, then loop over the line to get characters:

with open(filename, 'r') as f:
    for line in f:
        line = line.upper()
        for char in line:
            # process the char

Advantages:

  1. Uses a “with” block, so Python handles the book-keeping of closing
    the file when you are done.

  2. Doesn’t read one character at a time (slow!) or try to read the
    entire file all in one go (if the file is huge, you may run out of
    memory).

  3. Uppercases an entire line in one go, which will be faster than
    uppercasing one char at a time.

Thanks for that information.

For reference: Python Documentation: 7. Input and Output: 7.2.1. Methods of File Objects.

Thanks again. Is the “with” block really only used to “handle the book-keeping” as it were? Does it have another use outside of ensuring the file is closed when everything else is done?

“with” blocks can be used for, well, not quite anything, but close to
it. Any time you have a pattern that looks like:

open something
do some work
close it again

or like:

turn something on
do some work
turn it off again

it will be a good candidate to be written as a “with” block. The most
common example is opening a file, reading or writing to the file, then
closing it, but it is not the only example.