Python Check if There Is Input Before Reading
viii
INPUT VALIDATION
Input validation code checks that values entered past the user, such as text from the input() function, are formatted correctly. For case, if you want users to enter their ages, your code shouldn't have nonsensical answers such every bit negative numbers (which are outside the range of acceptable integers) or words (which are the incorrect data blazon). Input validation can also preclude bugs or security vulnerabilities. If yous implement a withdrawFromAccount() function that takes an argument for the amount to subtract from an business relationship, yous demand to ensure the amount is a positive number. If the withdrawFromAccount() role subtracts a negative number from the account, the "withdrawal" will end up adding coin!
Typically, we perform input validation by repeatedly asking the user for input until they enter valid text, as in the following example:
while True:
print('Enter your age:')
age = input()
endeavor:
age = int(age)
except:
impress('Please use numeric digits.')
continue
if historic period < one:
print('Please enter a positive number.')
go on
intermission
print(f'Your age is {age}.')
When you run this program, the output could look like this:
Enter your age:
five
Delight use numeric digits.
Enter your age:
-2
Delight enter a positive number.
Enter your age:
30
Your historic period is xxx.
When you run this code, you'll be prompted for your age until yous enter a valid one. This ensures that by the fourth dimension the execution leaves the while loop, the age variable will contain a valid value that won't crash the program afterward on.
Nonetheless, writing input validation code for every input() phone call in your program apace becomes slow. Likewise, you may miss certain cases and allow invalid input to pass through your checks. In this affiliate, you'll learn how to use the third-party PyInputPlus module for input validation.
The PyInputPlus Module
PyInputPlus contains functions similar to input() for several kinds of data: numbers, dates, email addresses, and more. If the user e'er enters invalid input, such as a badly formatted appointment or a number that is outside of an intended range, PyInputPlus will reprompt them for input just like our code in the previous section did. PyInputPlus as well has other useful features like a limit for the number of times information technology reprompts users and a timeout if users are required to respond within a fourth dimension limit.
PyInputPlus is not a part of the Python Standard Library, so you must install it separately using Pip. To install PyInputPlus, run pip install --user pyinputplus from the command line. Appendix A has consummate instructions for installing third-political party modules. To check if PyInputPlus installed correctly, import it in the interactive trounce:
>>> import pyinputplus
If no errors announced when you import the module, it has been successfully installed.
PyInputPlus has several functions for different kinds of input:
inputStr() Is like the congenital-in input() function but has the general PyInputPlus features. Y'all can also pass a custom validation office to it
inputNum() Ensures the user enters a number and returns an int or bladder, depending on if the number has a decimal bespeak in it
inputChoice() Ensures the user enters i of the provided choices
inputMenu() Is similar to inputChoice(), but provides a menu with numbered or lettered options
inputDatetime() Ensures the user enters a date and fourth dimension
inputYesNo() Ensures the user enters a "yeah" or "no" response
inputBool() Is similar to inputYesNo(), simply takes a "True" or "Fake" response and returns a Boolean value
inputEmail() Ensures the user enters a valid email address
inputFilepath() Ensures the user enters a valid file path and filename, and can optionally check that a file with that proper name exists
inputPassword() Is like the congenital-in input(), only displays * characters as the user types and then that passwords, or other sensitive information, aren't displayed on the screen
These functions volition automatically reprompt the user for as long every bit they enter invalid input:
>>> import pyinputplus as pyip
>>> response = pyip.inputNum()
five
'five' is not a number.
42
>>> response
42
The as pyip code in the import statement saves usa from typing pyinputplus each time we want to call a PyInputPlus function. Instead we tin utilise the shorter pyip name. If you take a await at the example, you lot see that unlike input(), these functions return an int or float value: 42 and 3.14 instead of the strings '42' and 'iii.14'.
Simply as you can pass a string to input() to provide a prompt, you can pass a string to a PyInputPlus function'south prompt keyword argument to display a prompt:
>>> response = input('Enter a number: ')
Enter a number: 42
>>> response
'42'
>>> import pyinputplus as pyip
>>> response = pyip.inputInt(prompt='Enter a number: ')
Enter a number: cat
'cat' is non an integer.
Enter a number: 42
>>> response
42
Apply Python's help() function to notice out more about each of these functions. For example, help(pyip.inputChoice) displays help information for the inputChoice() function. Complete documentation can exist establish at https://pyinputplus.readthedocs.io/.
Unlike Python's congenital-in input(), PyInputPlus functions have several additional features for input validation, as shown in the adjacent department.
The min, max, greaterThan, and lessThan Keyword Arguments
The inputNum(), inputInt(), and inputFloat() functions, which take int and float numbers, also accept min, max, greaterThan, and lessThan keyword arguments for specifying a range of valid values. For instance, enter the following into the interactive shell:
>>> import pyinputplus every bit pyip
>>> response = pyip.inputNum('Enter num: ', min=iv)
Enter num:iii
Input must be at minimum four.
Enter num:4
>>> response
iv
>>> response = pyip.inputNum('Enter num: ', greaterThan=4)
Enter num: 4
Input must be greater than iv.
Enter num: 5
>>> response
5
>>> response = pyip.inputNum('>', min=four, lessThan=half dozen)
Enter num: vi
Input must be less than 6.
Enter num: 3
Input must be at minimum 4.
Enter num: iv
>>> response
4
These keyword arguments are optional, but if supplied, the input cannot be less than the min statement or greater than the max argument (though the input tin exist equal to them). Also, the input must be greater than the greaterThan and less than the lessThan arguments (that is, the input cannot be equal to them).
The blank Keyword Statement
By default, blank input isn't allowed unless the blank keyword argument is ready to True:
>>> import pyinputplus as pyip
>>> response = pyip.inputNum('Enter num: ')
Enter num:(blank input entered here)
Blank values are non allowed.
Enter num: 42
>>> response
42
>>> response = pyip.inputNum(blank=Truthful)
(blank input entered hither)
>>> response
''
Apply blank=Truthful if y'all'd like to brand input optional so that the user doesn't need to enter anything.
The limit, timeout, and default Keyword Arguments
By default, the PyInputPlus functions volition continue to ask the user for valid input forever (or for equally long as the program runs). If y'all'd like a office to cease request the user for input afterward a certain number of tries or a sure amount of time, you can use the limit and timeout keyword arguments. Pass an integer for the limit keyword argument to determine how many attempts a PyInputPlus function will make to receive valid input before giving up, and pass an integer for the timeout keyword argument to determine how many seconds the user has to enter valid input earlier the PyInputPlus function gives upwards.
If the user fails to enter valid input, these keyword arguments volition cause the function to raise a RetryLimitException or TimeoutException, respectively. For example, enter the following into the interactive crush:
>>> import pyinputplus as pyip
>>> response = pyip.inputNum(limit=2)
blah
'blah' is not a number.
Enter num: number
'number' is not a number.
Traceback (near contempo call final):
--snip--
pyinputplus.RetryLimitException
>>> response = pyip.inputNum(timeout=10)
42 (entered after 10 seconds of waiting)
Traceback (most recent call last):
--snip--
pyinputplus.TimeoutException
When you utilise these keyword arguments and also laissez passer a default keyword argument, the function returns the default value instead of raising an exception. Enter the following into the interactive shell:
>>> response = pyip.inputNum(limit=2, default='N/A')
hello
'hello' is not a number.
world
'world' is not a number.
>>> response
'Due north/A'
Instead of raising RetryLimitException, the inputNum() function just returns the string 'Northward/A'.
The allowRegexes and blockRegexes Keyword Arguments
You can also use regular expressions to specify whether an input is allowed or non. The allowRegexes and blockRegexes keyword arguments take a list of regular expression strings to determine what the PyInputPlus role will accept or reject as valid input. For example, enter the following lawmaking into the interactive shell so that inputNum() will accept Roman numerals in addition to the usual numbers:
>>> import pyinputplus as pyip
>>> response = pyip.inputNum(allowRegexes=[r'(I|5|X|L|C|D|1000)+', r'nix'])
XLII
>>> response
'XLII'
>>> response = pyip.inputNum(allowRegexes=[r'(i|v|x|l|c|d|m)+', r'zero'])
xlii
>>> response
'xlii'
Of form, this regex affects simply what letters the inputNum() function volition have from the user; the function will even so take Roman numerals with invalid ordering such every bit 'XVX' or 'MILLI' because the r'(I|5|X|50|C|D|Grand)+' regular expression accepts those strings.
You lot can also specify a listing of regular expression strings that a PyInputPlus function won't accept by using the blockRegexes keyword argument. Enter the post-obit into the interactive shell so that inputNum() won't accept even numbers:
>>> import pyinputplus as pyip
>>> response = pyip.inputNum(blockRegexes=[r'[02468]$'])
42
This response is invalid.
44
This response is invalid.
43
>>> response
43
If you specify both an allowRegexes and blockRegexes argument, the let list overrides the block listing. For example, enter the following into the interactive vanquish, which allows 'caterpillar' and 'category' just blocks annihilation else that has the word 'cat' in it:
>>> import pyinputplus as pyip
>>> response = pyip.inputStr(allowRegexes=[r'caterpillar', 'category'],
blockRegexes=[r'true cat'])
cat
This response is invalid.
ending
This response is invalid.
category
>>> response
'category'
The PyInputPlus module'southward functions can salve yous from writing tedious input validation code yourself. Simply there's more than to the PyInputPlus module than what has been detailed here. Yous can examine its total documentation online at https://pyinputplus.readthedocs.io/.
Passing a Custom Validation Function to inputCustom()
You tin write a office to perform your own custom validation logic by passing the function to inputCustom(). For example, say you lot want the user to enter a series of digits that adds upwardly to 10. There is no pyinputplus.inputAddsUpToTen() function, simply you tin can create your own role that:
- Accepts a unmarried cord argument of what the user entered
- Raises an exception if the string fails validation
- Returns None (or has no render argument) if inputCustom() should return the string unchanged
- Returns a non-None value if inputCustom() should return a dissimilar cord from the one the user entered
- Is passed as the first statement to inputCustom()
For example, we tin create our own addsUpToTen() function, then pass it to inputCustom(). Annotation that the function call looks like inputCustom(addsUpToTen) and not inputCustom(addsUpToTen()) because we are passing the addsUpToTen() part itself to inputCustom(), not calling addsUpToTen() and passing its return value.
>>> import pyinputplus as pyip
>>> def addsUpToTen(numbers):
...numbersList = listing(numbers)
...for i, digit in enumerate(numbersList):
...numbersList[i] = int(digit)
...if sum(numbersList) != x:
...raise Exception('The digits must add upwardly to x, not %southward.' %
(sum(numbersList)))
...return int(numbers) # Return an int grade of numbers.
...
>>> response = pyip.inputCustom(addsUpToTen) # No parentheses after
addsUpToTen here.
123
The digits must add up to x, non 6.
1235
The digits must add up to ten, not 11.
1234
>>> response # inputStr() returned an int, not a string.
1234
>>> response = pyip.inputCustom(addsUpToTen)
hello
invalid literal for int() with base ten: 'h'
55
>>> response
The inputCustom() function also supports the general PyInputPlus features, such as the blank, limit, timeout, default, allowRegexes, and blockRegexes keyword arguments. Writing your own custom validation function is useful when it's otherwise difficult or impossible to write a regular expression for valid input, equally in the "adds up to x" instance.
Project: How to Continue an Idiot Decorated for Hours
Permit'due south utilize PyInputPlus to create a simple program that does the following:
- Ask the user if they'd similar to know how to continue an idiot busy for hours.
- If the user answers no, quit.
- If the user answers aye, go to Footstep 1.
Of course, we don't know if the user volition enter something as well "yes" or "no," and then we need to perform input validation. It would also be convenient for the user to exist able to enter "y" or "n" instead of the full words. PyInputPlus's inputYesNo() function volition handle this for us and, no matter what instance the user enters, return a lowercase 'aye' or 'no' string value.
When you lot run this program, it should expect similar the following:
Want to know how to go on an idiot busy for hours?
sure
'sure' is not a valid yes/no response.
Desire to know how to go on an idiot busy for hours?
aye
Want to know how to keep an idiot decorated for hours?
y
Want to know how to keep an idiot decorated for hours?
Yes
Want to know how to keep an idiot busy for hours?
Yes
Desire to know how to keep an idiot busy for hours?
YES!!!!!!
'Yep!!!!!!' is not a valid yes/no response.
Want to know how to proceed an idiot busy for hours?
TELL ME HOW TO Continue AN IDIOT Decorated FOR HOURS.
'TELL ME HOW TO KEEP AN IDIOT Busy FOR HOURS.' is not a valid yes/no response.
Want to know how to go along an idiot decorated for hours?
no
Thank y'all. Have a overnice mean solar day.
Open a new file editor tab and save it as idiot.py. Then enter the following code:
import pyinputplus as pyip
This imports the PyInputPlus module. Since pyinputplus is a flake much to type, we'll use the name pyip for curt.
while True:
prompt = 'Desire to know how to keep an idiot busy for hours?\north'
response = pyip.inputYesNo(prompt)
Next, while Truthful: creates an infinite loop that continues to run until it encounters a break argument. In this loop, nosotros phone call pyip.inputYesNo() to ensure that this function telephone call won't render until the user enters a valid answer.
if response == 'no':
break
The pyip.inputYesNo() call is guaranteed to only return either the string yeah or the cord no. If information technology returned no, and then our program breaks out of the infinite loop and continues to the last line, which thanks the user:
print('Give thanks you lot. Have a dainty twenty-four hours.')
Otherwise, the loop iterates once again.
You can also make use of the inputYesNo() office in not-English language languages past passing yesVal and noVal keyword arguments. For example, the Spanish version of this program would have these two lines:
prompt = '¿Quieres saber cómo mantener ocupado a un idiota durante horas?\northward'
response = pyip.inputYesNo(prompt, yesVal='sí', noVal='no')
if response == 'sí':
At present the user can enter either sí or s (in lower- or uppercase) instead of yes or y for an affirmative answer.
Project: Multiplication Quiz
PyInputPlus's features can be useful for creating a timed multiplication quiz. By setting the allowRegexes, blockRegexes, timeout, and limit keyword argument to pyip.inputStr(), you tin go out almost of the implementation to PyInputPlus. The less code you lot demand to write, the faster you lot tin write your programs. Let's create a plan that poses 10 multiplication problems to the user, where the valid input is the problem's right answer. Open a new file editor tab and save the file as multiplicationQuiz.py.
First, we'll import pyinputplus, random, and time. We'll proceed track of how many questions the plan asks and how many correct answers the user gives with the variables numberOfQuestions and correctAnswers. A for loop will repeatedly pose a random multiplication problem 10 times:
import pyinputplus every bit pyip
import random, time
numberOfQuestions = ten
correctAnswers = 0
for questionNumber in range(numberOfQuestions):
Inside the for loop, the programme will pick two unmarried-digit numbers to multiply. We'll use these numbers to create a #Q: North × Due north = prompt for the user, where Q is the question number (ane to ten) and Northward are the 2 numbers to multiply.
# Pick two random numbers:
num1 = random.randint(0, 9)
num2 = random.randint(0, 9)
prompt = '#%s: %s x %s = ' % (questionNumber, num1, num2)
The pyip.inputStr() part will handle most of the features of this quiz program. The argument we pass for allowRegexes is a list with the regex string '^%s$', where %s is replaced with the correct reply. The ^ and % characters ensure that the answer begins and ends with the right number, though PyInputPlus trims whatsoever whitespace from the start and cease of the user'southward response start just in case they inadvertently pressed the spacebar before or after their answer. The argument we pass for blocklistRegexes is a listing with ('.*', 'Wrong!'). The offset string in the tuple is a regex that matches every possible string. Therefore, if the user response doesn't match the right answer, the program will decline any other respond they provide. In that case, the 'Wrong!' string is displayed and the user is prompted to answer again. Additionally, passing 8 for timeout and 3 for limit will ensure that the user only has eight seconds and three tries to provide a correct respond:
try:
# Right answers are handled by allowRegexes.
# Wrong answers are handled past blockRegexes, with a custom message.
pyip.inputStr(prompt, allowRegexes=['^%s$' % (num1 * num2)],
blockRegexes=[('.*', 'Wrong!')],
timeout=8, limit=3)
If the user answers afterwards the 8-2d timeout has expired, even if they answer correctly, pyip.inputStr() raises a TimeoutException exception. If the user answers incorrectly more than than 3 times, it raises a RetryLimitException exception. Both of these exception types are in the PyInputPlus module, so pyip. needs to prepend them:
except pyip.TimeoutException:
print('Out of time!')
except pyip.RetryLimitException:
print('Out of tries!')
Remember that, just like how else blocks can follow an if or elif block, they tin optionally follow the concluding except cake. The code within the following else block will run if no exception was raised in the attempt block. In our case, that ways the code runs if the user entered the correct answer:
else:
# This cake runs if no exceptions were raised in the try block.
print('Right!')
correctAnswers += one
No matter which of the three messages, "Out of fourth dimension!", "Out of tries!", or "Correct!", displays, let's place a 1-2nd suspension at the end of the for loop to give the user time to read information technology. After the plan has asked 10 questions and the for loop continues, let's prove the user how many correct answers they fabricated:
time.sleep(ane) # Cursory interruption to let user run into the result.
impress('Score: %southward / %s' % (correctAnswers, numberOfQuestions))
PyInputPlus is flexible enough that y'all can utilize it in a wide variety of programs that have keyboard input from the user, equally demonstrated past the programs in this chapter.
Summary
It's like shooting fish in a barrel to forget to write input validation code, just without it, your programs will almost certainly have bugs. The values you expect users to enter and the values they actually enter can be completely different, and your programs need to be robust plenty to handle these exceptional cases. Yous tin use regular expressions to create your own input validation code, just for common cases, it's easier to utilise an existing module, such equally PyInputPlus. Y'all can import the module with import pyinputplus equally pyip so that you can enter a shorter name when calling the module's functions.
PyInputPlus has functions for inbound a diversity of input, including strings, numbers, dates, yeah/no, True/Fake, emails, and files. While input() ever returns a string, these functions render the value in an appropriate data blazon. The inputChoice() office allow you lot to select one of several pre-selected options, while inputMenu() also adds numbers or messages for quick selection.
All of these functions have the post-obit standard features: stripping whitespace from the sides, setting timeout and retry limits with the timeout and limit keyword arguments, and passing lists of regular expression strings to allowRegexes or blockRegexes to include or exclude particular responses. You'll no longer need to write your own tedious while loops that check for valid input and reprompt the user.
If none of the PyInputPlus module'south, functions fit your needs, but you lot'd still similar the other features that PyInputPlus provides, you lot can call inputCustom() and pass your ain custom validation office for PyInputPlus to use. The documentation at https://pyinputplus.readthedocs.io/en/latest/ has a complete listing of PyInputPlus'south functions and additional features. In that location's far more in the PyInputPlus online documentation than what was described in this chapter. There's no use in reinventing the bike, and learning to use this module volition salve you from having to write and debug lawmaking for yourself.
Now that you have expertise manipulating and validating text, it's time to learn how to read from and write to files on your computer's difficult drive.
Practice Questions
1. Does PyInputPlus come with the Python Standard Library?
2. Why is PyInputPlus ordinarily imported with import pyinputplus as pyip?
3. What is the difference between inputInt() and inputFloat()?
iv. How can you ensure that the user enters a whole number between 0 and 99 using PyInputPlus?
5. What is passed to the allowRegexes and blockRegexes keyword arguments?
six. What does inputStr(limit=3) practise if blank input is entered three times?
7. What does inputStr(limit=3, default='hello') practise if blank input is entered three times?
Practice Projects
For do, write programs to do the following tasks.
Sandwich Maker
Write a plan that asks users for their sandwich preferences. The program should utilize PyInputPlus to ensure that they enter valid input, such as:
- Using inputMenu() for a bread type: wheat, white, or sourdough.
- Using inputMenu() for a poly peptide type: chicken, turkey, ham, or tofu.
- Using inputYesNo() to ask if they want cheese.
- If and so, using inputMenu() to ask for a cheese type: cheddar, Swiss, or mozzarella.
- Using inputYesNo() to ask if they want mayo, mustard, lettuce, or tomato.
- Using inputInt() to ask how many sandwiches they desire. Make certain this number is ane or more.
Come up with prices for each of these options, and take your plan display a total toll afterward the user enters their choice.
Write Your Own Multiplication Quiz
To see how much PyInputPlus is doing for you, effort re-creating the multiplication quiz projection on your own without importing information technology. This program will prompt the user with 10 multiplication questions, ranging from 0 × 0 to 9 × 9. You'll need to implement the post-obit features:
- If the user enters the correct answer, the program displays "Correct!" for 1 second and moves on to the next question.
- The user gets iii tries to enter the correct answer before the program moves on to the adjacent question.
- Eight seconds after first displaying the question, the question is marked as wrong fifty-fifty if the user enters the correct respond after the 8-2d limit.
Compare your code to the code using PyInputPlus in "Projection: Multiplication Quiz" on page 196.
Source: https://automatetheboringstuff.com/2e/chapter8/
0 Response to "Python Check if There Is Input Before Reading"
Post a Comment