2

I am trying to convert input() data to int() with the following code:

prompt_text = "Enter a number: "
try:
  user_num = int(input(prompt_text))
except ValueError:
  print("Error")

for i in range(1,10):
  print(i, " times ", user_num, " is ", i*user_num)

even = ((user_num % 2) == 0)

if even:
  print(user_num, " is even")
else:
  print(user_num, " is odd")

I get the following odd error when I enter asd2 for example:

Enter a number: asd2 Error 
Traceback (most recent call last):   File "chapter3_ex1.py", line 8, in <module>
    print(i, " times ", user_num, " is ", i*user_num) 
NameError: name 'user_num' is not defined

What am I doing wrong?

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
  • 1
    add something like `quit()` to your `except ValueError`. right now your program doesn't stop execution on error. – sobolevn Nov 07 '15 at 18:31
  • 1
    Not entirely on point but you might want to consider using `raw_input()` and handling the validation parsing of the supplied value once you've got a string - https://docs.python.org/2/library/functions.html#raw_input, `input()` does an `eval` of the supplied input, effectively "turning it into code". This is unsafe. – Will Hogan Nov 07 '15 at 18:33
  • 2
    @Will The OP might be using Python3. – Bhargav Rao Nov 07 '15 at 18:34
  • Ahh, yes, great point :) – Will Hogan Nov 07 '15 at 18:40
  • 2
    Generally it's nice to give a more informative error message, and to allow the user another chance to enter correct input. See [Asking the user for input until they give a valid response](http://stackoverflow.com/questions/23294658/asking-the-user-for-input-until-they-give-a-valid-response) for some excellent examples. – PM 2Ring Nov 07 '15 at 19:37
  • sobolevn nailed it :) – Georgi Tsvetanov Tsenov Nov 08 '15 at 12:32
  • Please [accept](http://meta.stackexchange.com/questions/5234) an answer if you think it solves your problem. It will community at large to recognize the correct solution. This can be done by clicking the green check mark next to the answer. See this [image](http://i.stack.imgur.com/uqJeW.png) for reference. Cheers. – Bhargav Rao Dec 15 '15 at 21:34

3 Answers3

3

The problem that you are facing is that the interpreter raises the error in the try and executes the except block. After that it will start to execute everyline. This will throw the NameError

You can overcome that by putting the rest of the program into the else block.

prompt_text = "Enter a number: "

try:
    user_num = int(input(prompt_text))  

except ValueError:
    print("Error")

else:
    for i in range(1,10):
      print(i, " times ", user_num, " is ", i*user_num)

    even = ((user_num % 2) == 0)

    if even:
      print(user_num, " is even")
    else:
      print(user_num, " is odd")

Quoting from the Python tutorial

The try ... except statement has an optional else clause, which, when present, must follow all except clauses. It is useful for code that must be executed if the try clause does not raise an exception.

Another way is to use a sentinel value

prompt_text = "Enter a number: "
user_num = 0 # default value
try:
    user_num = int(input(prompt_text))
except ValueError:
    print("Error")

This will also work. However the results may not be as expected.


Protip - Use 4 spaces to indent

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
1

The problem isn't with the conversion to an int. user_num doesn't get a value if an exception is thrown, but it's used later.

prompt_text = "Enter a number: "
try:
  user_num = int(input(prompt_text)) # this fails with `asd2`
except ValueError:
  print("Error") # Prints your error

for i in range(1,10):
  print(i, " times ", user_num, " is ", i*user_num) # user_num wasn't assigned because of the error

even = ((user_num % 2) == 0)

if even:
  print(user_num, " is even")
else:
  print(user_num, " is odd")

You can fix this by putting the code that uses user_num in the try-block. I'll also add create a function to clean things up.

def is_even(num):
  return num%2 == 0

prompt_text = "Enter a number: "
try:
  user_num = int(input(prompt_text))
  for i in range(1,10):
    print(i, " times ", user_num, " is ", i*user_num)
  if is_even(user_num):
    print(user_num, " is even")
  else:
    print(user_num, " is odd")
except ValueError:
  print("Error")

See the ideone here.

erip
  • 16,374
  • 11
  • 66
  • 121
1

This may not be the cleanest solution but it addresses the problem, in your code user_num is not initialized unless it is a number.

prompt_text = "Enter a number: "
user_num = "no Input"
try:
  user_num = int(input(prompt_text))
except ValueError:
  print("Error")

if str(user_num).isnumeric():
  for i in range(1,10):
    print(i, " times ", user_num, " is ", i*user_num)

  even = ((user_num % 2) == 0)

  if even:
    print(user_num, " is even")
  else:
    print(user_num, " is odd")
else:
  print("You did not enter a number")
Nicole Cook
  • 316
  • 1
  • 5
  • 11
  • I wouldn't think that it would be a good idea to again check in an `if` condition. The other answers have shown the better way AFAIK. It is easier and cleaner to put everything in the `try` block. – Bhargav Rao Nov 07 '15 at 19:08