Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Python Python Collections (Retired) Lists Redux Shopping List Take Three

Patricia Snyder
Patricia Snyder
5,563 Points

try/except error

Hi, I'm attempting to add try and except to the shopping list script. and I keep getting the below error.

Traceback (most recent call last):
  File "shopping_list2.py", line 45, in <module>
    spot = int(index) -1
ValueError: invalid literal for int() with base 10: ' f'

Here is the portion of the code affected:

new_list = new_stuff.split(",")
        try:
            index = input("Add this at a certain spot? Press enter for the end of the list,  \n or give me a number. Currently {} items in the list.".format(len(shopping_list)))
        except ValueError:
            print("Please enter a number")
        else:
            if index:
                spot = int(index) -1
                for item in new_list:
                    shopping_list.insert(spot, item.strip())
                    spot += 1
            else:
                for item in new_list:
                    shopping_list.append(item.strip())

I've included the full code below.

Thank you so much for your help.

shopping_list=[]

def show_help():
    print("\nSeparate each item with a comma.\n")
    print("Type \n  DONE to quit \n  SHOW to see current list \n  DEL to delete an item \n  HELP to get this message\n")

def show_list():
    count = 1
    for item in shopping_list:
        print("{}: {}".format(count, item))
        count+=1

def del_item():
    delete = input("What item do you want to remove?  ")
    shopping_list.remove(delete)


print("Give me a list of things you want to shop for.")
show_help()

while True:
    new_stuff = input("> ")

    if new_stuff == "DONE":
        print("\nHere's your list:")
        show_list()
        break
    elif new_stuff == "HELP":
        show_help()
        continue
    elif new_stuff == "SHOW":
        show_list()
        continue
    elif new_stuff == "DEL":
        del_item()
    else: 
        new_list = new_stuff.split(",")
        try:
            index = input("Add this at a certain spot? Press enter for the end of the list,  \n or give me a number. Currently {} items in the list.".format(len(shopping_list)))
        except ValueError:
            print("Please enter a number")
        else:
            if index:
                spot = int(index) -1
                for item in new_list:
                    shopping_list.insert(spot, item.strip())
                    spot += 1
            else:
                for item in new_list:
                    shopping_list.append(item.strip())

4 Answers

John Lindsey
John Lindsey
15,641 Points

Is it because the int(index) is in the else block rather than a try statement? That appears to be what would cause the error if the input wasn't an string type of a number.

Patricia Snyder
Patricia Snyder
5,563 Points

THAT does look like it could be the culprit. I'll see what I can do to re-write it.

Thanks!

John Lindsey
John Lindsey
15,641 Points

You could make another variable that does the int() conversion in the try statement, and then just use that variable in the else statement.

Patricia Snyder
Patricia Snyder
5,563 Points

Great. I will give that a go.

Thanks again.

That's not going to work as well as you think. You're essentially telling the computer to try to see if there's a value for index, not try to see if there's a value error.

So 3 things that will apparently happen if you run your code:

1) You don't enter anything for index. It'll read your try block, check there's no index, and run your else block appending your list to the end of the list. So if this is the case, your code will run fine.

2) You enter a non-integer value as your index. It'll read your try block, see that there's an index, try subtracting it from 1, which won't work, and then run your except ValueError block. In this case, your code will also work fine.

3) You enter an actual integer into for your index. It's going to run your try block, see there's an index, and apply your list to that spot based on your index. AND THEN it's going to read your else block, appending it again to the end of your list.

Try this code instead:

else:
    new_list = new_stuff.split(",")
    index = input("Add this at a certain spot? Press enter for the end of the list, "
                  "or give me a number. Currently {} items in the list: ".format(
            len(shopping_list)))

    if index:
        try:
            spot = int(index) - 1
        except ValueError:
            print("That's not a number!")
            continue

        else:  
            for item in new_list:
                shopping_list.insert(spot, item.strip()) #strip removes the white space
                spot += 1 
    else:
        for item in new_list:
            shopping_list.append(item.strip())

Now what I don't understand is, for her code:

1) Why does it still work despite not having a "Continue" in the Except block? Shouldn't it theoretically just print "That's not a number." and then run the else block?

2) Is there any reason to always have an else block after a try/except block? It seems to work with or without it.

So looks like I answered my own question. Having an except block in addition to the try/except block is dependent on if you have a continue in the exception block. If you don't have a continue, you want an else block - otherwise, it'll print out the exception message and then run whatever is next. If you include the else block, there's no need to have a continue in the exception block. For example:

1) Example of having a "continue" but no else block.

    if index:
        try:
            spot = int(index) - 1
        except ValueError:
            print("That's not a number!")
            continue
        for item in new_list:
                shopping_list.insert(spot, item.strip()) #strip removes the white space
                spot += 1 

2) Example of having no "continue", but an else block.

    if index:
        try:
            spot = int(index) - 1
        except ValueError:
            print("That's not a number!")
        else:
            for item in new_list:
                shopping_list.insert(spot, item.strip()) #strip removes the white space
                spot += 1 

It's interesting to note that else blocks in Try/Except blocks run a little different than else's in "if" blocks. In the latter, else will only run if any of the "if" blocks don't trigger. However in the former, the "else" block will trigger even if the "try" triggers (but it won't trigger if the except block triggers). The best way for me to understand it is to view the "except" block as an "if" block. Hope that helps and wasn't too confusing.

Patricia Snyder
Patricia Snyder
5,563 Points

Thank you! That was very detailed. I appreciate it.

Patricia Snyder
Patricia Snyder
5,563 Points

I figured it out.

        index = input("Add this at a certain spot? Pres enter for the end of the list, \n or give me a number. Currently {} items in the list.".format(len(shopping_list)))

        #~ put try above index if statement
        try:
            if index:
                spot = int(index) - 1
                for item in new_list:
                    shopping_list.insert(spot, item.strip())
                    spot += 1
        #~ except goes directly after   
        except ValueError:
            print("Please use a number")

        else:
            for item in new_list:
                shopping_list.append(item.strip())