Python Forum
Dealing with errors in input
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Dealing with errors in input
#1
Hello

I am currently trying to create a small program which takes two numbers as given by the user and tells you if one can be divided by the other.
It works perfectly fine, but as a side subject I wanted to work out how to loop my program back to ask them to re-enter the digits if they type
something invalid such as letters.

Here is my program thus far:

# input asking the user for 2 numbers and assigning these numbers to variables as integers.
num, check = [int(x) for x in input("Please enter two numbers: ").split()]

# my function which determines whether one is divisible by the other
def num_divide_by_check(x, y):
	if x%y == 0:
		print(str(x) + " is divisible by " + str(y))  
	else:
		print(str(x) + " is not divisible by " + str(y))

# putting the collected values into my function 
num_divide_by_check(num, check)
input("Press enter to close")
The second problem I face is, if the user uses anything but spaces to split up the two numbers I ask for e.g. "+" or ",". Is there a away to make my program ignore these values, or must I just add into my input asking them to split it by a space, and have any other method again recognised as an error and looped back to be re-typed.

Many Thanks
Soup
Reply
#2
There are a number of ways you can deal with this. You could do two separate inputs to get the different numbers. You could be explicit about needing a space. You could replace other common delimiters with spaces before splitting (input('Enter two numbers: ').replace(',', ' ').split()). You could write a regular expression matching valid numbers, and use findall to get a list of valid numbers in the input.

If you want to give multiple chances to correct the input, a while True loop is often used:

while True:
    values = input('Enter two numbers: ')
    try:
        # to convert to integer
    except ValueError:
        print('Invalid input')
    else:
        break
Instead of (or in addition to) the try/except block, you might check for a valid range or other issues with if/else, again breaking if the input is valid.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
(Apr-09-2019, 12:08 PM)ichabod801 Wrote: There are a number of ways you can deal with this. You could do two separate inputs to get the different numbers. You could be explicit about needing a space. You could replace other common delimiters with spaces before splitting (input('Enter two numbers: ').replace(',', ' ').split()). You could write a regular expression matching valid numbers, and use findall to get a list of valid numbers in the input.

If you want to give multiple chances to correct the input, a while True loop is often used:

while True:
    values = input('Enter two numbers: ')
    try:
        # to convert to integer
    except ValueError:
        print('Invalid input')
    else:
        break
Instead of (or in addition to) the try/except block, you might check for a valid range or other issues with if/else, again breaking if the input is valid.

thanks for the answer!
could you explain the replace bit to me in a little more detail please showing how it works. ( I am trying to keep both numbers on the same input line). I've done the while true loop before, but I didn't know how to get it to measure both numbers at once without making a separate loop for each one
Reply
#4
One way of validating input i.e getting numbers out from whatever user writes without regex is by using built-in module itertools function groupby:

>>> from itertools import groupby
>>> user_input = ' a34+ *2'
>>> [int(''.join([*y])) for x, y in groupby(user_input, lambda char: char.isdigit()) if x == True]
[34, 2]
Explainer:
- group by whether character is digit or not (groupby(user_input, lambda char: char.isdigit()))
- give only groups which are True i.e groups of digits (if x == True)
- construct group of digits to string and convert to int (int(''.join([*y])))

Additional len() == 2 may be implemented in order to make sure that only two numbers are entered.

One should be aware of caveats of str.isdigit() ("This covers digits which cannot be used to form numbers in base 10, like the Kharosthi numbers.")
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#5
(Apr-09-2019, 12:37 PM)souprqtpie Wrote: could you explain the replace bit to me in a little more detail please showing how it works. ( I am trying to keep both numbers on the same input line). I've done the while true loop before, but I didn't know how to get it to measure both numbers at once without making a separate loop for each one

>>> value = '2, 3'                   # user enters with a comma
>>> value.split()                    # comma is retained by split()
['2,', '3']
>>> [int(v) for v in value.split()]  # comma prevents converting to integer
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '2,'
>>> value.replace(',', ' ')                            # replace gets rid of the comma
'2  3'
>>> value.replace(',', ' ').split()                    # you can chain it with split, to get the two numbers entered
['2', '3']
>>> [int(v) for v in value.replace(',', ' ').split()]  # now you can convert to integer
[2, 3]
In terms of measuring two numbers at once, it depends on what you are measuring. If you are just checking a range, you can use min and max:

if min(values) < low or max(values) > high:
    print('Please enter numbers in the range {} to {}.'.format(low, high))
If you are checking them with a function that returns True if the number is valid, you can use map and all:

if all(map(check_function, valid)):
    print('All numbers are valid')
Map will pass each number in valid as a parameter to check_function, and return a list of all the return values. All will return true if all the values in a sequence evaluate to True, and False if any of them don't.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#6
Quote:In terms of measuring two numbers at once, it depends on what you are measuring. If you are just checking a range, you can use min and max:

if min(values) < low or max(values) > high:
    print('Please enter numbers in the range {} to {}.'.format(low, high))
If you are checking them with a function that returns True if the number is valid, you can use map and all:

if all(map(check_function, valid)):
    print('All numbers are valid')
Map will pass each number in valid as a parameter to check_function, and return a list of all the return values. All will return true if all the values in a sequence evaluate to True, and False if any of them don't.

The replace part worked an absolute charm, thanks! I am however still struggling, I'll try and make my problem a little clearer, below is my code.
This function works if you input two integers with a comma or space (thanks to you!) Smile
However if you input something which is not an integer it errors. I've done this before on a single value, but setting it up for two values is causing me a problem.

num = None
check = None
while num is None:
	val1, val2 = [int(x) for x in input("Please enter two numbers: ").replace(",", " ").split()]
	try:
		num = int(val1)
	except ValueError:
		print("please enter valid numbers")
	try:
		check = int(val2)
	except ValueError:
		print("please enter valid numbers")

x = val1 - val2
print(x)

input("press enter to close")
p.s. I am super new to python still, so I appreciate your help and patience.

Soup
Reply
#7
You are converting on line 4, you want that in the try block. An error on either one will trigger the except part, so you just need one of those. You also need a break statement.

try:
    val1, val2 = [int(x) for x in input("Please enter two numbers: ").replace(",", " ").split()]
    break
except ValueError:
    print('Please enter valid numbers.')
If the error happens on the second line, it will skip to the except. If it doesn't happen (valid input), it will break out of the loop.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#8
(Apr-09-2019, 07:58 PM)ichabod801 Wrote: You are converting on line 4, you want that in the try block. An error on either one will trigger the except part, so you just need one of those. You also need a break statement.

try:
    val1, val2 = [int(x) for x in input("Please enter two numbers: ").replace(",", " ").split()]
    break
except ValueError:
    print('Please enter valid numbers.')
If the error happens on the second line, it will skip to the except. If it doesn't happen (valid input), it will break out of the loop.

That worked perfectly! I forgot that the input line actually tries to convert to integer so checks it already! Thanks for your help! much up votes :)
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Dealing with duplicates to an Excel sheet DistraughtMuffin 6 3,284 Oct-28-2020, 05:16 PM
Last Post: Askic
  Dealing with list coja56 2 2,830 Sep-18-2020, 09:32 PM
Last Post: perfringo

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020