Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Why does is an IndexError being raised in this code?

Here's the code:

while goal_keeper not in range(len(team_roster)):
    try:
            goal_keeper = input("Please select a goalkeeper by selecting the player number (1-{}). ".format(len(team_roster)))
            try: 
                int(goal_keeper)
            except ValueError:
                print ("Please enter a valid number.")
            if goal_keeper not in range(len(team_roster)):
                raise IndexError
            print("Great!!! The goalkeeper for this game will be {}".format(team_roster[goal_keeper - 1]))
            team_roster[goal_keeper-1] += " (Goalie)"
            print("Here is your current roster: ")
            for x in range(len(team_roster)):
                print (team_roster[x])

    except IndexError:
            print("That number is not valid. Please try again.")

This is a link to what this code is outputting when I enter "Alex" for goal_keeper. The user is supposed to input a number and I wanted to deal with this error: https://imgur.com/0Ig2dQk

I am wondering why it is returning "That number is not valid. Please try again.". To me, this implies that goal_keeper was not in the range of len(team_roster), but since the int() command never ran, goal_keeper should still be a string. How can a string be within a range? I'd expect this to spit out some nasty traceback.

I did find a solution. I figured out that I can make the second try encompass the entire block, and move the except ValueError to the bottom, it works the way I want it to. Here's the working code:

while goal_keeper not in range(len(team_roster)):
    try:
            goal_keeper = input("Please select a goalkeeper by selecting the player number (1-{}). ".format(len(team_roster)))
            try: 
                int(goal_keeper)
                if goal_keeper not in range(len(team_roster)):
                    raise IndexError
                print("Great!!! The goalkeeper for this game will be {}".format(team_roster[goal_keeper - 1]))
                team_roster[goal_keeper-1] += " (Goalie)"
                print("Here is your current roster: ")
                for x in range(len(team_roster)):
                    print (team_roster[x])
            except ValueError:
                print ("Please enter a valid number.")
    except IndexError:
        print("That number is not valid. Please try again.")

That said, I still don't understand why things happened the way they did in the first example. Thanks for the help. Also - sorry if imgur isn't the preferred way to share code, I couldn't figure out a cleaner wya to do it.

boi
boi
14,242 Points

Hey, ben! The first thing you should do is to learn how to put your code into proper format so that it can be analyzed properly, Click Here to learn the MarkDown basics.

Made the changes. Thanks!

1 Answer

Jeff Muday
MOD
Jeff Muday
Treehouse Moderator 28,720 Points

Good work on that, very logical and straightforward

Avoid nested try/except -- see below.

Even though it is syntactically valid to nest try/except blocks, it will not work in the way you expect. I learned that the hard way! The outer "except" ends up taking over.

The try/except block alters normal program flow so the inner "nested" except block is not reached.

x = 10
y = 0

try:
    print("OUTER try block")
    try:
        print("NESTED try block")
        print(x / y) # here is where the error occurs
    except TypeError as te:
        print("NESTED except block")
        print(te)
except ZeroDivisionError as ze:
    print("OUTER except block") # but this is where the error is handled.
    print(str(ze))

Output

OUTER try block
NESTED try block
OUTER except block
division by zero

The Python try/except/finally is an excellent structure to utilize. One thing that is super nice about it is that you can have multiple except blocks for different errors.

try:
   some_code_goes_here
except ErrorType1 as et1:
   some_error_handler1
except ErrorType2 as et2:
   some_error_handler2
except Exception as e:
   some_unknown_error_handler
finally:
   some_code_to_run_for_all

Got it, thank you!