I am just starting to learn Python and am trying to handle errors a user might input. All the program does is use the math module, asks the user for an integer and returns the factorial of the number.
I am trying to catch errors for negative numbers, floats and text.
If I enter an integer the code runs like it should.
When I enter a wrong value, like -9 or apple, the try/except seems to not catch the error and I get the traceback information. The user shouldn't see this.
Any suggestions or pointers?
import math
from datetime import datetime
import time
num = 0
start = 0
end = 0
# max value is 2147483647
#if __name__ == '__main__':
try:
num = input("Enter a number: ")
except OverflowError:
print("Input cannot exceed 2147483647")
except ValueError:
print("Please enter a non-negative whole number")
except NameError:
print("Must be an integer")
else:
start = datetime.now()
print("The factorial of ", num, " is : ")
print(math.factorial(int(num)))
end = datetime.now()
print(f"Time taken in (hh:mm:ss.ms) is {end - start}")
I am using Python 3.10 on a Windows 10 Pro (64-bit) PC if that matters.
Norman
Your code is missing the operation which can cause the exception: in fact, input('...') returns a string representing whatever user inputs. This means that your num variable is a string (you can check by printing type(num).
You have to try to cast it into an integer:
try:
num = int(input('...'))
except ValueError:
print('invalid input')
Be carefull: if user input the value "-3", it will be accepted: the string will be cast into the integer -3 and this is correct.
If user inputs words like 'apple' or floats like 3.14, the exception raised is ValueError.
My suggest is to do something like this:
try:
num = int(input('...'))
if num >= 0:
# computing factorial
else:
print('error: only positive numbers will be accepted')
return
except ValueError:
print('invalid input')
That is because input() do not raise an error just because you want just a number. You have to check the type of input by yourself and then also raise an error by yourself.
e.g.
if not isinstance("string", int):
raise ValueError
edit: also have a look here for more information about input(): https://www.python-kurs.eu/python3_eingabe.php
It always returns a string, so you have to convert your input actively in the type you want and make your type check during/after the conversion
I took the path yondaime offered and got pretty close to what I wanted. The final result is below.
I thank all of you for your comments. The last time I did anything even slightly like programming was in Fortran on punch cards on an IBM 360.
I apologize for asking such basic questions but really am trying.
The code that works but really doesn't point out exactly which fault happened. I will try to figure out how to convert the string in the input statement to a float and see if there is a remainder (modulo maybe?) so the user gets a better hint what was wrong.
import math
from datetime import datetime
import time
num = 0
start = 0
end = 0
try:
num = int(input('Enter a positive whole number: '))
if (num >= 0 and num <= 2147483647):
start = datetime.now()
print("The factorial of ", num, " is : ")
print(math.factorial(int(num)))
end = datetime.now()
else:
print('Number must be between 0 and 2147483647 are allowed.')
print(f"Time taken in (hh:mm:ss.ms) is {end - start}")
except ValueError:
print('Text or decimal numbers are not allowed. Please enter a whole number between 0 and 2147483647')
I have a lot time to learn because I'm bored in retirement ...
Norman
Related
This question already has answers here:
Asking the user for input until they give a valid response
(22 answers)
Closed 11 months ago.
I am working on a Paycheck calculator as a little side project for my portfolio and I have it so that users can input their own information (i.e. pay rate, hours worked, shift differentials, etc.) and parts of my code have inputs for variables:
payrate = float(input("What is your current payrate? $"))
When the code is run it asks the user to enter a value for their pay, but if they enter $20 instead of 20, I get:
ValueError: could not convert string to float: '$20'
How can I optimize my code so that it either ignores the $ when a user inputs something other than a float or it gives a rejection message to the user that I can write out myself in plain English so they know what to do?
Thank you!
Github link in case anyone wants to check it out for themselves (warning: still a massive WIP... so be gentle)
You an define a method called isfloat:
def isfloat(num):
try:
float(num)
return True
except ValueError:
return False
payrate = input("What is your current payrate? $")
if isfloat(payrate):
payrate = float(payrate)
# Do some math
else:
print("Please enter a number.")
exit()
print(payrate)
Something like this should do what your question asks:
while True:
s = input("What is your current payrate? $")
try:
payrate = float(s)
break
except ValueError:
print("Couldn't parse you input as a number. Please try again")
print(f"Thanks, payrate is {payrate}")
The loop keeps going until a float is successfully parsed. Each time a parse fails (in other words, each time our attempt to convert the string s to a float raises an exception), it prints an informational message in the except block.
I want to handle possible ValueErrors resulting from invalid user input but I still get the red errors in the console instead of the program printing 'Invalid entry' as I intended. I'm not sure what's going wrong.
input_number = input("How many numbers would you like the program to calculate the average of?\n>> ")
try:
input_number = int(input_number)
except ValueError:
print("Invalid entry")
for i in range(input_number):
input("Please enter a whole number (%i/%i numbers entered):\n>> " % (i + 1, input_number))
It seems to ignore my try except statement as the error appears on the line of the for statement, saying "TypeError: 'str' object cannot be interpreted as an integer". It still doesn't work even if I amend the except to be "except ValueError or TypeError".
The problem is that when you catch the ValueError, you don't do anything to fix input_number (i.e. make it an int), so the program continues past your try statement and into your range() call, which proceeds to raise another exception because input_number isn't an int.
Simply catching an exception doesn't fix the error that caused it to be raised in the first place. If you catch an exception, you need to understand why it raised, and do something appropriate to correct the situation; blindly catching an exception will often just lead to another error later in your program, as it did here.
One way to correct this situation is to prompt the user again:
while True:
try:
input_number = int(input(
"How many numbers would you like the program to calculate the average of?\n>> "
))
break
except ValueError:
print("Invalid entry")
With the above code, the loop continues until input_number is an int.
Since it looks like you'll be wanting to do this again, I'd suggest putting it in a function:
def input_number(prompt: str) -> int:
"""Prompt for a number until a valid int can be returned."""
while True:
try:
return int(input(prompt))
except ValueError:
print("Invalid entry")
n = input_number(
"How many numbers would you like the program to calculate the average of?\n>> "
)
numbers = [
input_number(f"Please enter a whole number ({i}/{n} numbers entered):\n>>")
for i in range(1, n+1)
]
print(f"Average: {sum(numbers)/len(numbers)}")
How many numbers would you like the program to calculate the average of?
>> I don't know
Invalid entry
How many numbers would you like the program to calculate the average of?
>> 4
Please enter a whole number (1/4 numbers entered):
>>5
Please enter a whole number (2/4 numbers entered):
>>42
Please enter a whole number (3/4 numbers entered):
>>???
Invalid entry
Please enter a whole number (3/4 numbers entered):
>>543
Please enter a whole number (4/4 numbers entered):
>>0
Average: 147.5
The clause should be
except (ValueError, TypeError):
...
I am just starting to learn Python and am trying to handle errors a user might input. All the program does is use the math module, asks the user for an integer and returns the factorial of the number.
I am trying to catch errors for negative numbers, floats and text.
If I enter an integer the code runs like it should.
When I enter a wrong value, like -9 or apple, the try/except seems to not catch the error and I get the traceback information. The user shouldn't see this.
Any suggestions or pointers?
import math
from datetime import datetime
import time
num = 0
start = 0
end = 0
# max value is 2147483647
#if __name__ == '__main__':
try:
num = input("Enter a number: ")
except OverflowError:
print("Input cannot exceed 2147483647")
except ValueError:
print("Please enter a non-negative whole number")
except NameError:
print("Must be an integer")
else:
start = datetime.now()
print("The factorial of ", num, " is : ")
print(math.factorial(int(num)))
end = datetime.now()
print(f"Time taken in (hh:mm:ss.ms) is {end - start}")
I am using Python 3.10 on a Windows 10 Pro (64-bit) PC if that matters.
Norman
Your code is missing the operation which can cause the exception: in fact, input('...') returns a string representing whatever user inputs. This means that your num variable is a string (you can check by printing type(num).
You have to try to cast it into an integer:
try:
num = int(input('...'))
except ValueError:
print('invalid input')
Be carefull: if user input the value "-3", it will be accepted: the string will be cast into the integer -3 and this is correct.
If user inputs words like 'apple' or floats like 3.14, the exception raised is ValueError.
My suggest is to do something like this:
try:
num = int(input('...'))
if num >= 0:
# computing factorial
else:
print('error: only positive numbers will be accepted')
return
except ValueError:
print('invalid input')
That is because input() do not raise an error just because you want just a number. You have to check the type of input by yourself and then also raise an error by yourself.
e.g.
if not isinstance("string", int):
raise ValueError
edit: also have a look here for more information about input(): https://www.python-kurs.eu/python3_eingabe.php
It always returns a string, so you have to convert your input actively in the type you want and make your type check during/after the conversion
I took the path yondaime offered and got pretty close to what I wanted. The final result is below.
I thank all of you for your comments. The last time I did anything even slightly like programming was in Fortran on punch cards on an IBM 360.
I apologize for asking such basic questions but really am trying.
The code that works but really doesn't point out exactly which fault happened. I will try to figure out how to convert the string in the input statement to a float and see if there is a remainder (modulo maybe?) so the user gets a better hint what was wrong.
import math
from datetime import datetime
import time
num = 0
start = 0
end = 0
try:
num = int(input('Enter a positive whole number: '))
if (num >= 0 and num <= 2147483647):
start = datetime.now()
print("The factorial of ", num, " is : ")
print(math.factorial(int(num)))
end = datetime.now()
else:
print('Number must be between 0 and 2147483647 are allowed.')
print(f"Time taken in (hh:mm:ss.ms) is {end - start}")
except ValueError:
print('Text or decimal numbers are not allowed. Please enter a whole number between 0 and 2147483647')
I have a lot time to learn because I'm bored in retirement ...
Norman
I have a countdown timer that asks for user input for a "lucky number". Once that number is entered, the timer starts to countdown and prints out a simple message.
My problem is that if the user input is not a number, I get the "Traceback (most recent call last) ValueError: invalid literal for int() with base 10"
I understand what that means, but I don't know how to make it bypass this condition so that the user input can be anything (not just numbers) and not give me an error, but rather just print out a message that would just say; "continue without lucky number"..-and just continue with the rest of the script..
Any help would be highly appreciated. Thanks.
Here is a screenshot of the code
treat the user input as a string and then use a try-except to determine whether or not it is a number
try:
number = int(stringvar)
except:
print("continue without lucky number")
you could also then generate a random number for your timer if the user did not enter a number
import time
import random
def countdown(t):
while t:
mins, secs = divmod(t, 60)
timer = "{:02d}:{:02d}".format(mins, secs)
print(timer, end='\r')
time.sleep(1)
t -= 1
num = input("Enter your lucky number: ")
isNum = False
try:
i = int(num)
isNum = True
except:
print("Continue without lucky number")
if isNum:
countdown(i)
else:
rand = random.randint(1, 100)
countdown(rand)
print(f"timer number is: {rand}")
that can be your whole timer program.
If you want to give a certain message if it is not an integer instead of running the function then you can either use an if... else loop or try... except loop. For example:
try:
countdown(int(t))
except ValueError:
if input("Continue without lucky number?") == "y":
countdown(5)
As stated in the Zen of python
Errors should never pass silently.
Unless explicitly silenced.
However, apart from catching the error, you can do another thing in my opinion. Say your variable name is var,
if not var.isdigit():
var = ord(var)
Here, the functin ord() will return the ASCII value of the character which will be an integer obviously and your code will run successfully.
Python isn't recognizing any number apart from 1 as an integer. When i enter a number to be multiplied the program will run the except ValueError even though i have entered an integer. This is the code i have.
Total = 0
Tsl = 100
receipt = open("Receipt.txt", "w")
while True:
try:
Prod_Code = input("Enter a code or Done to get your final receipt: ")
if len(Prod_Code) == 8:
int(Prod_Code)
with open("Data Base.txt", "r") as searchfile:
for line in searchfile:
if Prod_Code in line:
print(line)
Quantity = input("What quantity of this product do you want? ")
Total += float(line.split(",")[2] * int(Quantity))
print(Quantity)
print(Total)
receipt.write(line)
elif Prod_Code == "Done":
print("Bye Bye")
print(receipt)
receipt.close
exit()
else:
print("Incorrect length, try again")
except ValueError:
print("You must enter an integer")
The error occurs when i enter any other number than 1 when i enter the quantity. If anyone can see the problem any input will be appreciated
The problem is that
Total += float(line.split(",")[2] * int(Quantity))
multiplies the string line.split(",")[2] by the Quantity converted to integer. And then attempts to convert the resulting string to a float.
Eg, if line.split(",")[2] is '1.2' and Quantity is '3' then
line.split(",")[2] * int(Quantity)
results in '1.21.21.2', which can't be converted to float. :)
Instead do
Total += float(line.split(",")[2]) * int(Quantity)
BTW, you aren't actually closing the receipt file. You're just emitting the method name and discarding it. So change
receipt.close
to
receipt.close()
Even better: use with blocks to open all your files so they get closed automatically.
I should also mention that the plain exit() function is primarily intended for use in the interactive interpreter, and it's not guaranteed to exist in all environments. To ensure portability use sys.exit() instead. OTOH, it's not really needed here, you can just break out of that while loop.
One reason can be in inputing the Promo_Code , you are using input so if your promo code is abcdefgh then you must input it as 'abcdefgh' or "abcdefgh" because input in python 2 cannot take automatic decisions . For sake of simplicity always use raw_input() for inputting strings,
Also in your elif convert reciept.close to reciept.close().