Correct way to validate user input in Python [closed] - python

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am working my way through some Python tutorials one of the things that keeps coming up is user input and i just wanted to check that i am validating it correctly and not going about it the long way around.
I have written the code below and only need to ask for the day month and year but if i needed to start asking for address phone number name etc etc this would grow and grow is that normal?
def get_input( i ):
while True:
# We are checking the day
if i == 'd':
try:
day = int( raw_input( "Please Enter the day: " ) )
# If the day is not in range reprint
if day > 0 and day < 32:
#Need to account for short months at some point
return day
else:
print 'it has to be between 1 and 31'
except ( ValueError ):
print "It has to be a number!"
elif i == 'm':
# We are checking the month
month = raw_input( 'Please enter ' +
'in words the month: '
).strip().lower()
if month in months: # use the dict we created
return month
else:
print 'Please check you spelling!'
elif i == 'y':
# Now the year
try:
year = int( raw_input( "Please Enter the year" +
"pad with 0's if needed: " ) )
#make we have enough digits and a positive
if year > 0 and len( year ) == 4:
return year
except ( ValueError, TypeError ):
print "It has to be a four digit number!"

Why don't you just have the user input the whole date in one go, and try it out to validate it?
from time import strptime
def get_date():
while True:
date = raw_input("Please enter a date in DD/MM/YYYY format: ")
try:
parsed = strptime(date, "%d/%m/%Y")
except ValueError as e:
print "Could not parse date: {0}".format(e)
else:
return parsed[:3]
year, month, day = get_date()
This will catch errors like 29/2/2011 but accept valid inputs like 29/2/2012.
If you'd like to accept several formats, just make a list of the format strings you want to accept and try them out one after another on the input, until you find one that works. But watch out for the problem of usage overloading.
For validating phone numbers I'd just go for a regexp. If you've never used regexps before there's a nice python regexp howto here. Addresses are very free form, so I don't think I'd bother validating them beyond restricting the length and doing basic security checking, especially if you're accepting international addresses.
But in general, if there's a python module for it you should just try to create an instance based on the input and catch the errors, like I do for the time module in the above example.
Don't even try to validate names. Why not? Look at this article. :)

Perhaps a framework like colander might be helpful here:
http://docs.pylonsproject.org/projects/colander/en/latest/?awesome

Related

Test user input until conditions are met

In python, I need the input of a user to be between a range of years.
Using if statement returns the error (if he's out of range) to the user and invite him to make another choice of year.
The second time he chooses a year need to be tested again with the same conditions. Which doesn't happen yet.
What would be the best solution to have his input tested all over again, until conditions are met ?
Here's some piece of the actual code
year = input("Enter a year between 1900 and 2099 : ")
if year >= "1900" or year <= "2099":
year = (input("The year you entered is out of range, please try again : "))
year = int(year)
Thanks in advance
Explanation:
You can use a while loop. A while loop will run until a certain condition is False. In this case it will run until the break keyword is used, because the condition will always be True. You can also use try and except do make sure the input it an integer. And use continue to start the loop again if it is not an integer.
Code:
prompt = "Enter a year between 1900 and 2099: "
while True:
year = input(prompt)
try:
year = int(year)
except ValueError:
prompt = "The year you entered is out of range, please try again : "
continue
if year >= 1900 or year <= 2099:
break
else:
prompt = "The year you entered is out of range, please try again : "

Why isn't this extracting the price correctly? Every price comes out to 0? Also it said 'payment' was being referenced before it was defined? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
# Sample line of text from file (Ford,F150,55000;)
filename = 'carPrice.txt'
def main():
all_prices= {}
try:
with open(filename) as fh:
for line in fh:
make, model, price = line.strip().split(',')
all_prices[(make,model)]=price.strip()
income = float(input("Enter your monthly income amount:"))
print("Your monthly income amount is",income,)
make = input("Enter Make of the car:")
print("You selected a",make,)
model = input("Enter Model of the car:")
print("You selected a",model,)
price_value=0
for x in price:
if x == (make,model):
price_value=price[x]
print("The price of that car is",price_value,)
payment = (price_value* 0.80)/60
print("The monthly payment is",payment,)
if (payment < 0.11*income):
print("The monthly payment of",payment,"= Acceptable Risk")
return "Acceptable"
else:
print("The monthly payment of",payment,"= Unacceptable Risk")
return "Unacceptable"
# Exception added to enable troubleshooting of errors on lines
except OSError as e:
print(e.errno)
if __name__ == '__main__':
main()
With respect, the code seems to be a bit all over the place, specifically in regards to price. If this is an exact copy of your code I think you may have lost track of what 'price' actually is.
For example here:
for x in price:
if x == (make,model):
price_value=price[x]
However, price here is a string value you pulled from the file e.g. £100. You're then iterating over that £, 1, 0, 0 and checking it against the make and model.
Finally you make the price_value an index of this string e.g.
price[x] # could be price["£"]
This would then cause an exception.
I'd go through your code again and look to make sure you're referencing price, price_value and all_prices where you actually want them

Write a basic program that takes number and returns its corresponding month abbreviation

I'm trying to write a basic function that takes a number and returns the abbreviation of each month. It sounds simple enough, but how can I use a "try-except"block to handle any exceptions?
Here's what I have so far.
def month():
months = "JanFebMarchAprilMayJuneJulyAugSepOctNovDec"
n = eval(input("Enter month Number: "))
pos = (n-1)*3
monthAbbrev = months
return monthAbbrev
I guess my question is how can I put in a try-expect handle indexes that are out of range?
I'm completely lost here. Thanks for your help
This simply returns the month at the correct index and if it doesn't exist it retruns the String Error replace it by whatever you need.
def month(n):
months = ("Jan", "Feb", "Mar", ...)
try:
return months[n-1]
except IndexError:
return "Error"
import datetime
mydate = datetime.datetime.now()
mydate.strftime("%b")
Get month name from number
Surround that with a try except to catch any errors

Creating an age calculator using python by calculating current year - birth year

I've looked all over stack overflow and so I really need help. I'm making a program that is supposed to calculate the age of a person by asking for their birth year, validating their birth year is correct, as in a whole number, and not words or any other invalid types of answers. And then subtracting the birth year from our current year. I'm having trouble with the inputting our current year and subtracting the user input birth year from it.
# Function Boolean is_valid_integer(String input_string)
# Declare Boolean is_valid
#
# is_valid = is input_string a valid integer?
# Return is_valid
# End Function
def is_valid_integer(input_string):
try:
val = int(input_string)
is_valid = True
except ValueError:
is_valid = False
return is_valid
# Function Integer get_year_born()
# Declare Boolean is_valid
#
# Display "What year were you born in? "
# Input input_string
# Set is_valid = is_valid_integer(input_string)
# While Not is_valid
# Display "Please only enter whole years."
# Input input_string
# is_valid = is_valid_integer(input_string)
# End While
# input_integer = int(input_string)
# Return input_integer
# End Function
def get_year_born():
input_string = input("What year were you born in? ")
is_valid = is_valid_integer(input_string)
while not is_valid:
input_string = input("Please only enter whole years. ")
is_valid = is_valid_integer(input_string)
input_integer = int(input_string)
return input_integer
# Function Integer calculate_difference()
# difference = 2017 - input_integer
# End Function
import datetime
def calculate_difference(difference):
difference = 2017 - input_integer
return difference
# Module calculate_age_year()
# Set born = get_year_born()
# Call calculate_difference()
# End Module
def calculate_difference():
print("Your age is: ", difference)
calculate_age_year()
After trying to import datatime into my coding, it didn't work well. I was also not looking to calculate specific days and/or time, and so I removed those part of the suggested coding, maybe that had something to do with it?
My purpose for this program is really to just calculate years, so if I'm born in 2000, I'd like the program to calculate from 2017, meaning I'd be 17 years old as of right now.
My first function is the loop to void out false inputs, the second function is to get the year the user was born in, the third function is supposed to be calculating the difference between the current date and the user's birth date, and the fourth function outputting the user's actual age.
To work with the dates in Python, you can use the module datetime.
To validate the error, a pythonic way of doing would be to use try...catch to convert the user input to a date time. Catch the possible errors and do your error management from there.
Here is a simple example:
import datetime
def print_age():
year = raw_input('Enter your age (YYYY/MM/DD): ')
try:
year = [int(i) for i in year.split('/')]
birth_data = datetime.date(year[0], year[1], year[2])
today = datetime.date.today()
time_diff = today - birth_data
print('Your age is: {} year and {} days'. format(
time_diff.days // 365, time_diff.days % 365))
except ValueError, KeyError:
# Do your error management here
print('Please use the format YYYY/MM/DD')
print_age()
With this, it should be relatively simple to return True or False and put the function in a loop.
Edit
Here is a piece of code that asks the user for his year of birth and prints the difference:
import datetime
year = None
while year is None:
try:
user_input = raw_input('Enter your date of birth (YYYY): ')
year = int(user_input)
except ValueError:
print('Your did not enter a valid year!')
print('You were born {} years ago'.format(datetime.datetime.now().year - year))
It does not check for the validity of the year though, if you enter 61241, it will not return an error.
You can add a layer of verification that check the range of the year if you wish.

Python: comparing dates and print out the first one

This is probably very simple, but I am a beginner in python and I wanted to compare birthday dates by prompting a user to enter a date in MM-DD format. No year because year is current year (2011). It will then prompt the user to enter another date, and then the program compares it to see which one is first. Then it prints out the earlier day and it's weekday name.
Example: 02-10 is earlier than 03-11.
02-10 is on thursday and 03-11 is on friday
I just started learned modules and I know i'm supposed to use the datetime module, a date class and strftime to get the weekday name. I don't really know how to put it all together.
If someone can help me get started that would really help! I have some bits and pieces together:
import datetime
def getDate():
while true:
birthday1 = raw_input("Please enter your birthday (MM-DD): ")
try:
userInput = datetime.date.strftime(birthday1, "%m-%d")
except:
print "Please enter a date"
return userInput
birthday2 = raw_input("Please enter another date (MM-DD): ")
if birthday1 > birthday2:
print "birthday1 is older"
elif birthday1 < birthday2:
print "birthday2 is older"
else:
print "same age"
There are a few problems I can see in the code you've posted. I hope it will be helpful to point some of these out, and provide a somewhat rewritten version:
Indentation is broken, but I guess this might just be problems pasting it into Stack Overflow
strftime is for formatting times, not parsing them. You want strptime instead.
In Python, True has a capital T.
You're defining the getDate function but never using it.
You would never exit your while loop, since you don't break after getting the input successfully.
It's considered bad style to use "camel case" for variable and method names in Python.
You use the word "older" in reference to the dates, but without a year you can't say if one person is older than the other.
You catch any exception thrown when you try to parse the date, but don't display it or check its type. That's a bad idea since if you've mistyped a variable name (or some similar typo) on that line, you won't see the error.
Here's a rewritten version of your code that fixes those problems - I hope it's clear from the above why I made those changes:
import datetime
def get_date(prompt):
while True:
user_input = raw_input(prompt)
try:
user_date = datetime.datetime.strptime(user_input, "%m-%d")
break
except Exception as e:
print "There was an error:", e
print "Please enter a date"
return user_date.date()
birthday = get_date("Please enter your birthday (MM-DD): ")
another_date = get_date("Please enter another date (MM-DD): ")
if birthday > another_date:
print "The birthday is after the other date"
elif birthday < another_date:
print "The birthday is before the other date"
else:
print "Both dates are the same"
There are two main functions that are used for converting between a date object and a string: strftime and strptime.
strftime is used for formatting. It returns a string object.
strptime is used for parsing. It returns a datetime object.
More info in the docs.
Since what you want is a datetime object, you would want to use strptime. You can use it as follows:
>>> datetime.datetime.strptime('01-23', '%m-%d')
datetime.datetime(1900, 1, 23, 0, 0)
Note that not having the year being parsed will set the default to 1900.
Well, datetime.date.strftime requires datetime object instead of string.
In your case the best thing is to create date manually:
import datetime
...
birthday1 = raw_input("Please enter your birthday (MM-DD): ")
try:
month, day = birthday1.split('-')
date1 = datetime.date(2011, int(month), int(day))
except ValueError as e:
# except clause
# the same with date2
And then when you have two dates, date1 and date2, you can just do:
if d1 < d2:
# do things to d1, it's earlier
else:
# do things to d2, it'2 not later

Categories