Why doesn't this code trigger a ValueError? - python

I'm trying to trigger an error when the "chunk_size" is zero, or greater than the length of the "sequence." When I call this function with a chunk_size of 4, and a sequence that equals "123" it doesn't throw an error. What did I do wrong?
def slices(sequence,chunk_size):
position=0
mini_list=[]
answer=[]
while chunk_size<=len(sequence) and chunk_size>0:
try:
for char in sequence:
if len(sequence[position:position+chunk_size])==chunk_size:
mini_seq = sequence[position:position+chunk_size]
for digit in mini_seq:
mini_list.append(int(digit))
answer.append(mini_list)
mini_list=[]
position+=1
return answer
break
except ValueError:
print "Oops! That was no valid number. Try again..."
print slices("012", 4)

It doesn't throw a ValueError, because you raise it within the while block, and the while block is entered only when the required condition of chunk_size being < 0 or > len(str) is not met.
Hence, to correct this, move the error raising part of your code out of the while loop. In fact, your placement of the condition within while is wrong, instead convert it to an if statement. Also, a break before a return statement won't make any sense.
So your code becomes
while True:
try:
if chunk_size<=len(sequence) and chunk_size>0:
for char in sequence:
if len(sequence[position:position+chunk_size])==chunk_size:
mini_seq = sequence[position:position+chunk_size]
for digit in mini_seq:
mini_list.append(int(digit))
answer.append(mini_list)
mini_list=[]
position+=1
return answer
else:
raise ValueError
except ValueError:
print "Oops! That was no valid number. Try again..."
Further, instead of raising an error to validate whether the data is in the right format, you can do away with raising the exception itself, and achive the same result with a simple if-else block:
while True:
if chunk_size<=len(sequence) and chunk_size>0:
for char in sequence:
if len(sequence[position:position+chunk_size])==chunk_size:
mini_seq = sequence[position:position+chunk_size]
for digit in mini_seq:
mini_list.append(int(digit))
answer.append(mini_list)
mini_list=[]
position+=1
return answer
else:
print "Oops! That was no valid number. Try again..."

Related

Python ValueError is it possible to get the Incorrect Value without string parsing?

I have this bit of code :
while True:
try:
start = int(input("Starting number: "))
fin = int(input("Ending number: "))
amount = int(input("Count by: "))
except ValueError as verr:
print('error : ', verr,'\n restarting ....')
else:
break
I would like to intercept the inputing of '' just hitting return as a signal to exit the loop inside the except block. Is there any way to get the value that raises the ValueError (I dont know how int() is able to return a ValueError and dont know about the latter either) other than parsing the ValueError __repr__ , for example :
invalid literal for int() with base 10: 'èèè' or the one I want to intercept
invalid literal for int() with base 10: '' ?
You could save the input value before the conversion and use that to check.
while True:
try:
_start = _fin = _amount = None
start = int(_start:=input("Starting number: "))
fin = int(_fin:=input("Ending number: "))
amount = int(_amount:=input("Count by: "))
except ValueError as verr:
if _start == "" or _fin == "" or _amount == "":
break
print('error : ', verr,'\n restarting ....')
else:
break
I think I would just get the inputs as strings then put an if statement to catch the case of '' or whatever else before converting to int and catching ValueErrors. This might offend if you are a stickler for concise code though.
Or as you say, parse the repr with something like .split(':')[-1]
Since the error is raised without passing the function argument and is formatted as string, there is no way to get the value directly from the error, what you can do is store it separately as a variable and then check the variable directly like so:
while True:
data = {"start": 0, "fin": 0, "amount": 0}
try:
for i in data:
x = input(f"Enter the value for {i}")
x = int(x)
data[i] = x
except ValueError:
if x == "":
break
Others have already posted possible solutions for your problem but to answer your question directly.
Question: Python ValueError is it possible to get the Incorrect Value without string parsing?
Answer: No it is not. ValueError only stores a message string and nothing else. You can get that message by str(verr) or verr.args[0]. The int(...) call already creates the full message and doesn't pass it's input string seperatly to the ValueError in any way. :/

while loop until input is has fulfilled two statements

def ask_input(prompt, error):
while True:
value = input(prompt)
try:
int(value) > 1
break
except ValueError:
print(error)
else:
return value
So I want to make simple function that returns value if its integrel and greater than 1. So far the function seems to accept anything I put in. Do I need to make multiple loops or can I integrate both of statement in a while loop?
Use if statement:
while True:
value = input(prompt)
try:
if int(value) > 1:
return int(value) # return the value if condition met
except ValueError as error:
print(error)
Your code prompts the user for anything that can be converted to an integer, whether or not it is > 1, then return None. This is not what you intended.
There are 2 different problems here:
int(value) > 1
If the input value is not parsable as an integer, then this will raise a ValueError that you catch and handle properly.
If the input value is parsable as an integer, then int(value) will convert it to an actual integer which will be compared to 1. The result of this comparison, however, is completely ignored since it is not stored in a variable or used.
Then the break will immediately leave the while loop, then the end of ask_input is reached, without a return statement. Because of that the else clause of your try is ignored.
I suggest the following code:
def ask_input(prompt, error):
while True:
value = input(prompt)
try:
if int(value) > 1:
return value
except ValueError:
print(error)
Use a try/except to accept only integers. Then test the input for the greater than 1 condition using an if condition, return the value if it satisfies the condition. It's better to use raw_input() in this case as you want an integer literal as input, where as input() can also evaluate expressions potentially leading to unsanitized input.
def ask_input(prompt, error):
while True:
try:
value = int(raw_input(prompt))
if value > 1: # Return the number if it's greater than 1.
return value
except ValueError: # Catch exception if value is not a base 10 int.
print error

How to get only numbers as a response in python?

I'm very new to python, in fact, to programming in general. I'm trying to do a program that compares three numbers and determines which one is smaller. I got the code done, but now i need to make it only accept numbers, and still running when it finds a literal value. For example, code will be ok if you put any number, but when you type a string value it crashes. here is the code
num1=0;
num2=0;
num3=0;
num1=int((raw_input("Type below the first number \n")));
num2=int((raw_input("Type below the second number\n")));
num3=int((raw_input("Type below the third number \n")));
if (num1<num2) and (num1<num3):
print "%i is the smallest number of all three"% num1;
elif (num2<num1) and (num2<num3):
print "%i is the smallest number of all three"% num2;
elif (num3<num2) and (num3<num1):
print "%i is the smallest number of all three"% num3;
elif (num1==num2) or (num1==num3) or (num2==num3):
print "Two equal numbers have been written.";
A simple while loop. You may put this in a function.
while True:
try:
num1=int((raw_input("Type below the first number \n")))
break
except ValueError: # catch the *specific* exception
print("Enter numbers only")
Read more on exceptions:
Handling Exceptions in Python
The most important point is probably to separate concerns, ie. keeping user input separate from validation. You've gotten a couple of good solutions using exceptions. Here is a solution that manually validates the input:
def is_int(strval):
"""A string represents an int if all characters are digits.
Returns True if strval represents a valid int, otherwise False.
"""
for ch in strval:
if not ch.isdigit(): # if '0' <= ch <= '9':
return False
return True
def read_int(prompt='Type number: '):
"""Read one integer from user.
"""
while True:
val = raw_input(prompt)
if is_int(val):
return int(val, 10) # the 10 is the radix (base)
else:
print 'That is not a number.., try again'
numbers = []
for pos in 'first', 'second', 'third':
numbers.append(read_int('Type %s number: ' % pos))
to use the exception handling code, all you have to do is change is_int:
def is_int(strval):
try:
int(strval, 10)
except ValueError:
# int() raised an exception, so strval is not an int
return False
else:
# int() didn't raise an exception, so it is an int
return True
it is also possible to be a bit more concise when finding the smallest:
def smallest(a, b, c):
if b > a < c: # if a is less than both b and c..
return a
if a > b < c:
return b
if a > c < b:
return c
return "Error: two of the numbers must be equal!"
you can call it like so:
smallest(numbers[0], numbers[1], numbers[2])
but Python has a shorthand that does exactly that which looks like:
smallest(*numbers)
def getNumber(i):
try:
num = int(raw_input("type in number %s : " %i))
return num
except Exception as e:
print('This is not a valid number')
return getNumber(i)
numbers = []
for i in range(1,4):
numbers.append(getNumber(i))
print(numbers)
You can simply add the input getting code in try except block and handle the ValueError exception with some meaningful code.
try:
num1=int((raw_input("Type below the first number \n")));
num2=int((raw_input("Type below the second number\n")));
num3=int((raw_input("Type below the third number \n")));
except ValueError:
print "Please enter integer only."
exit(-1)

Python excepting input only if in range

Hi I want to get a number from user and only except input within a certain range.
The below appears to work but I am a noob and thought whilst it works there is no doubt a more elegant example... just trying not to fall into bad habits!
One thing I have noticed is when I run the program CTL+C will not break me out of the loop and raises the exception instead.
while True:
try:
input = int(raw_input('Pick a number in range 1-10 >>> '))
# Check if input is in range
if input in range(1,10):
break
else:
print 'Out of range. Try again'
except:
print ("That's not a number")
All help greatly appreciated.
Ctrl+C raises a KeyboardInterruptException, your try … except block catches this:
while True:
try:
input = int(raw_input('Pick a number in range 1-10 >>> '))
except ValueError: # just catch the exceptions you know!
print 'That\'s not a number!'
else:
if 1 <= input < 10: # this is faster
break
else:
print 'Out of range. Try again'
Generally, you should just catch the exceptions you expect to happen (so no side effects appear, like your Ctrl+C problem). Also you should keep the try … except block as short as possible.
There are several items in your code that could be improved.
(1) Most importantly, it's not a good idea to just catch a generic exception, you should catch a specific one you are looking for, and generally have as short of a try-block as you can.
(2) Also,
if input in range(1,10):
would better be coded as
if 1 <= input < 10:
as currently function range() repeatedly creates a list of values form 1 to 9, which is probably not what you want or need. Also, do you want to include value 10? Your prompt seems to imply that, so then you need to adjust your call to range(1, 11), as the list generated will not include the upper-range value. and the if-statement should be changed to if 1 <= input <= 10:
You can use this code:
def read_int(prompt, min, max):
while True:
try:
val = int(input(prompt))
except ValueError:
print('Error: wrong input')
else:
if(min <= val < max): # this is faster
break
else:
print('Error: the value is not within permitted range (min..max)')
return val
v = read_int("Enter a number from -10 to 10: ", -10, 10)
print("The number is:", v)

How to determine when input is alphabetic?

I been trying to solve this one for a while and can't seem to make it work right.. here is my current work
while True:
guess = int(raw_input('What is your number?'))
if 100 < guess or guess < 1:
print '\ninvalid'
else:
.....continue on
Right now I have made it so when a user input a number higher than 100 or lower than 1, it prints out "invalid". BUT what if i want to make it so when a user input a string that is not a number(alphabetic, punctuation, etc.) it also returns this "invalid" message?
I have thought about using if not ...isdigit(), but it won't work since I get the guess as an integer in order for the above range to work. Try/except is another option I thought about, but still haven't figured out how to implement it in correctly.
You can use exception handling:
try:
guess = int(raw_input('What is your number?'))
if not (1 <= guess <= 100):
raise ValueError
# .....continue on
except ValueError:
print '\ninvalid'
That way, \ninvalid will be printed if the user either inputs a non-numeric string or inputs a numeric string greater than 100 or smaller than 1.
EDIT: Okay, I submit to the x < y < z syntax. Still think it loses some of its charm when it's used with not, though.
while True:
try:
guess = int(raw_input("..."))
except EOFError:
print "whoa nelly! EOF? we should probably exit"
break # or sys.exit, or raise a different exception,
# or don't catch this at all, and let it percolate up,
# depending on what you want
except ValueError:
print "illegal input: expected an integer"
else:
if not (1 <= guess <= 100):
print "out of range"
else:
print "processing guess... (but if it wasn't 42, then it's wrong)"
break # out of while loop after processing

Categories

Resources