0

I am executing the below code to catch input that is not a number or the number not within the range. i could catch the assertionerror but not the value error. can someone help me understand why i am not catching the valueerror?

What i am trying to do: i am getting the input from the user to see whether x is a number and it falls within the range specified that is min and max. if the input fails the validation, i should request the user to input the value again until the validation is passed so: when x = <<string>>, i should get "Enter a valid int" message. When x not within range, i should get "Enter a number between -10 and 10".

def readint(x,min,max):
    try:
        #x=int(input("Enter number betwen min and max: "))
        assert (x<=max and x>=-min)
    except ValueError:
         print("Enter a valid int")
    except AssertionError:
        print("Enter a number between -10 and 10")
        
    except NameError:
        print("Enter a valid int")


while True:
    readint(x=int(input("Enter number betwen min and max: ")),min=-10,max=10)
Maharajaparaman
  • 141
  • 3
  • 12
  • 2
    The place where you're calling `int(input(...))` isn't inside the `try` (it's outside the function entirely), so it won't be caught by the `ValueError`. – Green Cloak Guy Apr 02 '21 at 03:56
  • but i am passing the parameter to the function right? how could i catch the assertion error then? – Maharajaparaman Apr 02 '21 at 03:58
  • 1
    Beside the point, but you should never got a `NameError` unless you're aiming for Python 2 compatibility, in which case there are a ton more errors you'd also need to catch. Are you aiming for Python 2 compatibility? – wjandrea Apr 02 '21 at 03:59
  • 2
    The expression `int(input(...))` gets evaluated _before_ it gets passed into the function and the function gets executed. – Green Cloak Guy Apr 02 '21 at 03:59
  • Why did you comment out the `x=int(input(...))` line? That would solve the problem, though you'd also need to make some other adjustments. – wjandrea Apr 02 '21 at 04:04
  • how can i get the parameter for x, inside the function – Maharajaparaman Apr 02 '21 at 04:04
  • 1
    If you want to detect an exception that happens in code that runs *before you call the function*, then you need to do that detection *outside the function, in the place where you make the call*. If you want the function to do all the exception handling, then it also has to do all the work that could raise an exception. It's very simple. We aren't time travelers here. – Karl Knechtel Apr 02 '21 at 04:13
  • Sort of related: [Asking the user for input until they give a valid response](https://stackoverflow.com/q/23294658/4518341) – wjandrea Apr 02 '21 at 14:47

2 Answers2

1

You will get ValueError when a conversion from str to int fails. I modified your program, so the error is thrown within the try/except block:

def readint(low, high):
    try:
        x = int(input(f"Enter number betwen {low} and {high}, inclusive: "))
        assert (low <= x and x <= high)
    except ValueError:
         print("Enter a valid int")
    except AssertionError:
        print(f"Enter a number between {low} and {high}, inclusive")
    except NameError:
        print("Enter a valid int")

while True:
    readint(-10, 10)

The following is from running the above code:

Enter number betwen min and max: 1
Enter number betwen min and max: 22
Enter a number between -10 and 10
Enter number betwen min and max: -1
Enter number betwen min and max: -22
Enter a number between -10 and 10
Enter number betwen min and max: asdf
Enter a valid int

When I entered asdf that blew up the conversion to integer, and a ValueError was thrown, so we see "Enter a valid int".

Mike Slinn
  • 7,705
  • 5
  • 51
  • 85
  • Cannot seem to turn off syntax coloring for the output. Tried text, plaintext and no language hint. – Mike Slinn Apr 02 '21 at 04:51
  • `none` is the easiest way to turn off syntax highlighting. I fixed it for you :) – wjandrea Apr 02 '21 at 14:48
  • FYI, you can simplify the range check: `min <= x <= max`. Also, it's a good idea to avoid builtin names like `min` and `max` since they shadow the builtins; personally I'd use `low` and `high` instead. You don't need to change the code, I'm just mentioning :) – wjandrea Apr 02 '21 at 15:06
  • I renamed min and max, thanks, and also corrected the prompt that no longer showed the values of min and max. However, your suggestion on the range check did not work :( – Mike Slinn Apr 02 '21 at 15:38
  • Really, it didn't work? Try `assert low <= x <= high` – wjandrea Apr 02 '21 at 16:01
  • @MikeSlinn your code will not work as it will get in to a never ending loop – Maharajaparaman Apr 03 '21 at 06:09
  • @Maharajaparaman That is the point of `while True`. The code works just fine. Output is as shown. Try for yourself. – Mike Slinn Apr 03 '21 at 12:33
0

The answer is:

def readint( min, max):
    while True:
        try:
            x = int(input("Please enter a number: "))
            assert (x<=max and x>=min)
            return x
            break
        except ValueError:
            print("Enter a valid int")
        except AssertionError:
            print("Enter a number between -10 and 10")
    
        except NameError: 
            print("Enter a valid int")
#

v = readint( -10, 10)
print("The number is:", v)
Maharajaparaman
  • 141
  • 3
  • 12
  • This code assumes a different spec than the OP. Instead of 'keep reading something forever, and take action each time', this code perform 'read one value, and keep trying until you get it'. This changes the meaning. – Mike Slinn Apr 03 '21 at 12:35