1

I wrestled with this for several hours, the figured it out. Of course it seems painfully obvious to me now, but maybe one day someone else will get stuck in the same place, so I thought I'd ask-and-answer. Of course any corrections or interpretations are welcome.

Abridged code:

bearNames = {
    'grizzly' : 'GZ',
    'brown' : 'BR',
}

bearAttributes = {
    'GZ' : 'huge and light brown',
    'BR' : 'medium and dark brown',
}

print("Type the name of a bear:")
userBear = input("Bear: ")

beartruth = True
while beartruth == True:

    try:
        print("Abbreviation is ", bearNames[userBear])
        print("Attributes are ", bearAttributes[bearNames[userBear]])
        print("beartruth: ", beartruth)
        beartruth = False
        print("beartruth: ", beartruth)

    except:
        print("Something went wrong - did you not type a bear name?")
        print("beartruth: ", beartruth)

Problem - entering something which isn't a bear loops the "except" part forever. What I want to happen should be fairly obvious - if the user enters something which isn't in bearNames, it should trigger the except, print the error and head back to try.

Chris_Rands
  • 38,994
  • 14
  • 83
  • 119
fishkake
  • 41
  • 1
  • 1
  • 6
  • find out what your error is then except [error that you have] so that it actually catches something – L_Church Jan 25 '18 at 09:56
  • Hint: You don't change anything within your except and you don't reach the `beartruth = False` line. – filmor Jan 25 '18 at 09:56
  • `input()` needs to be *inside* the loop – Chris_Rands Jan 25 '18 at 09:57
  • 1
    Possible duplicate of [Asking the user for input until they give a valid response](https://stackoverflow.com/questions/23294658/asking-the-user-for-input-until-they-give-a-valid-response) – Chris_Rands Jan 25 '18 at 09:58
  • @filmor That was a bit more than a *hint* :D – Ma0 Jan 25 '18 at 10:00
  • L_Church - I thought it was acceptable to have a catch-all except clause? – fishkake Jan 25 '18 at 10:05
  • 1
    @fishkake There is only one `Error` that you are expecting this code to throw and that is `KeyError`. So let yourself be surprised if something **different is raised**. It would be good to know. – Ma0 Jan 25 '18 at 10:08
  • Regarding the duplicate - yes, the question you mention contains the solution, but as this was a mistake, any correct use of while, try, except also contains the solution. I think this question specifies this mistake clearly, and I think it is a mistake that many might make. But I'm new to Python (and new to SO), and I am happy to be proven wrong. So am I correct in leaving this for voters to decide? Thanks all of you! – fishkake Jan 25 '18 at 10:12
  • Ev. Kounis - I didn't think of it like that, good call. – fishkake Jan 25 '18 at 10:14

2 Answers2

2

Since your were asking for some corrections or interpretations.

From your code

try:
    print("Abbreviation is ", bearNames[userBear])
    print("Attributes are ", bearAttributes[bearNames[userBear]])
    print("beartruth: ", beartruth)
    beartruth = False
    print("beartruth: ", beartruth)

except:
    print("Something went wrong - did you not type a bear name?")
    print("beartruth: ", beartruth)

You can be specific (and I would recommend it) with Exceptions to make sure you isolate the error that you may be expecting.

try:
    print("Abbreviation is ", bearNames[userBear])
except KeyError:
    print("Something went wrong - did you not type a bear name?")
    print("beartruth: ", beartruth)
else:
    print("Attributes are ", bearAttributes[bearNames[userBear]])
    print("beartruth: ", beartruth)
    beartruth = False
    print("beartruth: ", beartruth)

Doing it that way, you know that the Bear wasn't actually one. And only if the Bear is a real one you go into the else block to do something else.

If you have made a mistake in the last 4 lines, the exception raised will be different and will not be hidden by the generic

except:

block, which would also be hiding other errors, but you would believe it was wrong input from the user.

Because you are in a while loop, you can alternatively do:

try:
    print("Abbreviation is ", bearNames[userBear])
except KeyError:
    print("Something went wrong - did you not type a bear name?")
    print("beartruth: ", beartruth)
    continue  # go back to the beginning of the loop

# There was no error and continue wasn't hit, the Bear is a bear
print("Attributes are ", bearAttributes[bearNames[userBear]])
print("beartruth: ", beartruth)
beartruth = False
print("beartruth: ", beartruth)
mementum
  • 3,153
  • 13
  • 20
  • I might be stating the obvious but this is the problem with learning to code on your own, without some community. You learn the way to do something, but you don't learn the fifteen ways of doing something which then lead to best practice and better code later on. My code works. Your code is better than mine. And as a result, my code will be better the next time. This is why I came here! I'm marking your post as the "answer" because it does contain the answer like mine does, but it contains more value. – fishkake Jan 26 '18 at 09:36
1

The answer I eventually figured out was to put the input() inside the while. To explain...

The code as-written first asks the user for input, then begins the while. If the user enters'grizzly' the try succeeds, and bearTruth is set to false which breaks the loop. (Perhaps a break statement would serve a purpose here, but I haven't got as far as break statements yet :) )

If the user enters something which isn't a bear, that input is done, and the try begins. It fails, but we are already inside the while, and the user input is set. So the try happens again with the same value for userBear, fails again, and loops forever.

Maybe one day someone as silly as me will have this problem and find this solution.

fishkake
  • 41
  • 1
  • 1
  • 6