Categories
Flask

Getting Started with Python Web Development with Flask

Flask is a simple web framework written in Python.

In this article, we’ll look at how to develop simple Python web apps with Flask.

Create the Project

First, we need to install Python 3 if it’s not installed already.

It comes with scripts to create a virtual environment so we don’t have to install anything else.

We can create a project by running:

$ mkdir flask-app
$ cd flask-app
$ python3 -m venv venv

on Linux.

We create the project folder and the virtual environment.

On Windows, we create the flask-app project folder and inside it, we run:

$ py -3 -m venv venv

to create the virtual environment.

Activate the Environment

We then activate the virtual environment.

To do that, we run:

$ . venv/bin/activate

in the project folder in Linux.

On Windows, we run:

> venvScriptsactivate

to do the same thing.

Install Flask

Once we install the virtual environment, we run:

$ pip install Flask

to install the Flask package.

A Minimal App

Now in the flask-app project folder, we create app.py and write:

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

to create a hello world app.

Flask(__name__) creates the Flask app.

@app.route is a decorator to add the route.

We return our response to as text in the hello_world function.

Then to run our app, we run:

$ export FLASK_APP=app.py
$ flask run

to run our app on Linux.

On Windows, we run:

> set FLASK_APP=app.py
> python -m flask run

to set the FLASK_APP environment variable and run our app.

The FLASK_APP environment variable should be set to the file name of the entry point.

Now we can go to http://127.0.0.1:5000/ in the browser and see ‘hello world’ displayed on the screen.

Debug Mode

We can turn on debug mode by setting the FLASK_END environment variable to development .

We can run:

export FLASK_ENV=development

to do that on Linux.

On Windows, we run:

set FLASK_ENV=development

to do the same thing.

Routing

We can add more than one route into our app.

For example, we can write:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return 'Welcome'

@app.route('/hello')
def hello():
    return 'Hello, World'

Then when we go to http://127.0.0.1:5000/, we see ‘Welcome’.

And when we go to http://127.0.0.1:5000/hello, we see ‘Hello, World’.

Routing with Variables

We can make our routes more useful with variables.

For example, we can write:

from flask import Flask
from markupsafe import escape
app = Flask(__name__)

@app.route('/user/<username>')
def show_user_profile(username):
    return 'User %s' % escape(username)

@app.route('/post/<int:post_id>')
def show_post(post_id):
    return 'Post %d' % post_id

@app.route('/path/<path:subpath>')
def show_subpath(subpath):
    return 'Subpath %s' % escape(subpath)

to create an app with routes that take route parameters.

<username> is the URL parameter placeholder.

We can access it with the username parameter.

escape escapes the URL parameter so we can use it safely.

We specified the data type it takes with the int and path substrings.

int is an integer. path is a path string.

So if we go to http://localhost:5000/path/foo/bar, we get ‘Subpath foo/bar’.

And if we go to http://localhost:5000/post/2, we get ‘Post 2’.

And if we go to http://localhost:5000/user/foo, we get ‘User foo’.

We can specify the following types:

  • string — accepts any text without a slash (default)
  • int — accepts positive integers
  • float — accepts positive floating-point values
  • path — like string but also accepts slashes
  • uuid — accepts UUID strings

Conclusion

We can create simple apps with ease with Flask.

Categories
Python

Validating Python Inputs with PyInputPlus

Python is a convenient language that’s often used for scripting, data science, and web development.

In this article, we’ll look at how to validating Python inputs with the PyInputPlus.

Validation Inputs

We use the PyInputPlus package to validate inputs from retrieved from the command line.

To use it, we have to install it. We run pip install pyinputplus to install the package.

Then we can use the following functions in the module to validate inputs:

  • inputStr — it’s like input but we can validate custom validations into it.
  • inputNum — ensures user enters a number and returns an int or float depending on if the number has a decimal point or not
  • inputChoice — ensures user enters of one the provided choices
  • inputMenu — it’s like inputChoice but provides a menu with number or lettered options
  • inputDatetime — ensures user enter a date and time
  • inputYesNo — ensures user enters yes or no
  • inputBool — ensures user enters True or False
  • inputEmail — ensures user enters email address
  • inputFilePath — checks that a user enters a file path
  • inputPassword — like input , but displays * in place of whatever is entered

We can use the module as follows:

import pyinputplus  
print('What is your age?')  
age = pyinputplus.inputNum()  
print('Your age is', age)

The code above asks user to enter their age. If they enter their age, then we display the last line.

Otherwise, we display an error message until they enter a number.

We can pass in the prompt text to the function. For instance, we can write:

import pyinputplus  
age = pyinputplus.inputNum(prompt='What is your age?')  
print('Your age is', age)

It works the same way as before except the 'What is your age?’ message doesn’t add a new line.

The min, max, greaterThan, and lessThan Keyword Arguments

We can check if the number entered is in the range we want with min , max , greaterThan , and lessThan keywords.

They do as their names suggest. For instance:

import pyinputplus  
age = pyinputplus.inputNum(prompt='What is your age?',  min=0)  
print('Your age is', age)

The code above will check if a number 0 or bigger is entered. If we enter an invalid number, we’ll get an error message until we enter a valid number.

The blank Keyword Argument

We can disallow blank inputs with by passing in a boolean argument for the blank parameter.

For example, we can write:

import pyinputplus  
age = pyinputplus.inputNum(prompt='What is your age?',  min=0, blank=False)  
print('Your age is', age)

Then we get Blank values are not allowed. error if we entered a blank value. We can’t proceed until we enter a valid number.

The limit, timeout, and default Keyword Arguments

PyInputPlus functions will continue to ask the same question until we enter a valid value.

To change this, we can use pass in an argument for the limit parameter to limit the number of tries allowed.

For instance, we can write:

import pyinputplus  
age = pyinputplus.inputNum(prompt='What is your age?',  min=0, limit=2)  
print('Your age is', age)

to limit the number of tries for answer the 'What is your age?' question to 2.

When we don’t enter a valid number after 2 tries, we get an error.

To set a default value, we can pass in an argument to the default parameter. For instance, we can write:

import pyinputplus  
age = pyinputplus.inputNum(prompt='What is your age?',  min=0, default='0', limit=2)  
print('Your age is', age)

When running the code above, if we didn’t enter a valid number after 2 tries, then it’ll print 'Your age is 0' on the screen since we set the default value to 0.

We can set the timeout parameter to limit the time that our program waits for an input to be entered.

For example, we can write:

import pyinputplus  
age = pyinputplus.inputNum(prompt='What is your age?',  timeout=1)  
print('Your age is', age)

After waiting for a second, we’ll get a TimeoutException thrown if nothing is entered.

The allowRegexes and blockRegexes Keyword Arguments

We can set a list of regex strings to the allowRegexes parameter to the PyInputPlus functions.

For example, if we want to make sure the user enters a phone number, we can write:

import pyinputplus  
phone = pyinputplus.inputNum(prompt='What is your phone?',  allowRegexes=[r'\d{3}-\d{3}-\d{4}', r'None'])  
print('Your phone is', phone)

In the code above, we allow phone numbers to be entered as the input value by setting a list of regex with the phone number regex to it.

Then we have to enter a phone number or 'None' before we can proceed.

Conclusion

We can use the PyInputPlus package to validate command line input values.

It has functions to checking various kinds of inputs like numbers, emails, date and time, yes or no, and so on.

Also, we can limit the range of the values that are entered for numbers and so check against regexes so that anything can be checked for the given format.

Categories
Python

Custom Input Validation Python Inputs with PyInputPlus

ython is a convenient language that’s often used for scripting, data science, and web development.

In this article, we’ll look at how to do custom input validation with PyInputPlus.

Passing a Custom Validation Function to inputCustom()

We can use the inputCustom function to validate any input by users,

It accepts a single string argument of what the user entered, raises an exception if the string fails validation, returns None if inputCustom should return the string unchanged, and returns non-None values if inputCustom should return a different string from the one that’s entered.

The function is passed in as the first argument to inputCustom .

For instance, we can use it as follows:

import pyinputplus  
import re  
def check_phone(phone):    
  if bool(re.match(r'\d{3}-\d{3}-\d{4}', phone)) == False:  
    raise Exception('Invalid phone number')  
  return phoneprint('What is your phone number?')  
phone_num = pyinputplus.inputCustom(check_phone)  
print('Your number is', phone_num)

In the code above, we defined the check_phone function, which checks if the entered phone number is a valid phone number or not. If it isn’t, then it raises an exception.

Otherwise, we return the phone number.

Then we pass in the check_phone function to the inputCustom function.

When we run the program, then we can’t get past the prompt until we entered a valid phone number.

Otherwise, we get an error.

Whatever we return in check_phone is returned by inputCustom if validation succeeds.

Creating a Menu with inputMenu

We can use the inputMenu function to create a simple menu. It takes a list of options as strings. Also, we can set the lettered option to add letters to our choices if set to True . We can add numbers to our menu by setting the numbered option to False .

For instance, we can write the following to create a simple menu:

import pyinputplusfruit = pyinputplus.inputMenu(['apple', 'banana', 'orange'], lettered=True, numbered=False)  
print('Chosen fruit', fruit)

Then we can type in a letter to make a choice.

Narrowing Choices with inputChoice

We can use the inputChoice function to allow users to enter a value. The only valid inputs are the choices that we set.

For instance, we can write:

import pyinputplusfruit = pyinputplus.inputChoice(\['apple', 'banana', 'orange'\])  
print('Chosen fruit', fruit)

Then we get:

Please select one of: apple, banana, orange

displayed on the screen.

Once we entered one of the answers listed above, we can proceed.

Conclusion

We can use the inputCustom function to validate any input we want. It takes a validation function as an argument.

The function we pass in takes the input value as a parameter.

It should raise an exception if the input fails validation. Otherwise, it should return the value that’s entered or something derived from it.

inputCustom returns whatever it’s returned with the validation function.

We can create a menu with the inputMenu function and create an input that only accepts a few choices with the inputChoice function.

Categories
Python

Manipulating File Paths with Python

Python is a convenient language that’s often used for scripting, data science, and web development.

In this article, we’ll look at how to read and write files with Python.

Files and File Paths

A file has a filename to reference the file. It also has a path to locate the file’s location.

The path consists of the folder, they can be nested and they form the path.

Backslash on Windows and Forward Slash on macOS and Linux

In Windows, the path consists of backslashes. In many other operating systems like macOS and Linux, the path consists of forward slashes.

Python’s standard pathlib library knows the difference and can sort them out accordingly. Therefore, we should use it to construct paths so that our program will run everywhere.

For instance, we can import pathlib as follows and create a Path object as follows:

from pathlib import Path  
path = Path('foo', 'bar', 'foo.txt')

After running the code, path should be a Path object like the following if we’re running the program above on Linux or macOS:

PosixPath('foo/bar/foo.txt')

If we’re running the code above on Windows, we’ll get a WindowsPath object instead of a PosixPath object.

Using the / Operator to Join Paths

We can use the / operator to join paths. For instance, we can rewrite the path we had into the following code:

from pathlib import Path  
path = Path('foo')/'bar'/'foo.txt'

Then we get the same result as before.

This will also work on Windows, macOS, and Linux since Python will sort out the path accordingly.

What we shouldn’t use is the string’s join method because the path separator is different between Windows and other operating systems.

For instance:

path = '/'.join(['foo', 'bar', 'foo.txt'])

isn’t going to work on Windows since the path has forward slash.

The Current Working Directory

We can get the current working directory (CWD), which is the directory the program is running on.

We can change the CWD with the os.chdir function and get the current CWD with the Path.cwd function.

For instance, we can write:

from pathlib import Path  
import os  
print(Path.cwd())  
os.chdir(Path('foo')/'bar')  
print(Path.cwd())

Then we get:

/home/runner/AgonizingBasicSpecialist  
/home/runner/AgonizingBasicSpecialist/foo/bar

as the output.

As we can see, chdir changed the current working directory, so that we can use manipulate files in directories other than the ones that the program is running in.

The Home Directory

The home directory is the root directory of the profile folder of the user’s user account.

For instance, we can write the following:

from pathlib import Path  
path = Path.home()

Then the value of path is something likePosixPath(‘/home/runner’) .

Absolute vs. Relative Paths

An absolute path is a path that always begins with the root folder. A relative is a path that’s relative to the program’s current working directory.

For example, on Windows, C:\Windows is an absolute path. A relative path is something like .\foo\bar . It starts with a dot and foo is inside the current working directory.

Creating New Folders Using the os.makedirs() Function

We can make a new folder with the os.makedirs function.

For instance, we can write:

from pathlib import Path  
Path(Path.cwd()/'foo').mkdir()

Then we make a foo directory inside our current working directory.

Handling Absolute and Relative Paths

We can check if a path is an absolute path with the is_absolute method.

For instance, we can write:

from pathlib import Path  
is_absolute = Path.cwd().is_absolute()

Then we should see is_absolute being True since Path.cwd() returns an absolute path.

We can call os.path.abspath to returns a string with of the absolute path of the path argument that we pass in.

For instance, given that we have the directory foo in the current working directory, we can write:

from pathlib import Path  
import os  
path = os.path.abspath(Path('./foo'))

to get the absolute path of the foo folder.

We then should get something like:

'/home/runner/AgonizingBasicSpecialist/foo'

as the value of path .

os.path.isabs(path) is a method that returns True is a path that is absolute.

The os.path.relpath(path, start) method will return a string of the relative path from the start path to path .

If start isn’t provided, then the current working directory is used as the start path.

For instance, if we have the folder /foo/bar in our home directory, then we can get the path of ./foo/bar relative to the home directory by writing:

from pathlib import Path  
import os  
path = os.path.relpath(Path.home(), Path('./foo')/'bar')

Then the path has the value ‘../../..’ .

Conclusion

We can use the path and os modules to construct and manipulate paths.

Also, we can also use the / with Path objects to create a path that works with all operating systems.

We can also path in paths to the Path function to construct paths.

Python also has methods to check for relative and absolute paths and the os module can construct relative paths from 2 absolute paths.

Categories
Python

Using Regex with Python

Python is a convenient language that’s often used for scripting, data science, and web development.

In this article, we’ll look at how to use regex with Python to make finding text easier.

Finding Patterns of Text with Regular Expressions

Regular expressions, or regexes, are descriptions for a pattern of text.

For instance, \d represents a single digit. We can combine characters to create regexes to search text.

To use regexes to search for text, we have to import the re module and then create a regex object with a regex string as follows:

import re  
phone_regex = re.compile('\d{3}-\d{3}-\d{4}')

The code above has the regex to search for a North American phone number.

Then if we have the following string:

msg = 'Joe\'s phone number is 555-555-1212'

We can look for the phone number inside msg with the regex object’s search method as follows:

import re  
phone_regex = re.compile('\d{3}-\d{3}-\d{4}')  
msg = 'Joe\'s phone number is 555-555-1212'  
match = phone_regex.search(msg)

When we inspect the match object, we see something like:

<re.Match object; span=(22, 34), match='555-555-1212'>

Then we can return a string representation of the match by calling the group method:

phone = match.group()

phone has the value '555-555-1212' .

Grouping with Parentheses

We can use parentheses to group different parts of the result into its own match entry.

To do that with our phone number regex, we can write:

phone_regex = re.compile('(\d{3})-(\d{3})-(\d{4})')

Then when we call search , we can either get the whole search string, or individual match groups.

group takes an integer that lets us get the parts that are matched by the groups.

Therefore, we can rewrite our program to get the whole match and the individual parts of the phone number as follows:

import re  
phone_regex = re.compile('(\d{3})-(\d{3})-(\d{4})')  
msg = 'Joe\'s phone number is 123-456-7890'  
match = phone_regex.search(msg)  
phone = match.group()  
area_code = match.group(1)  
exchange_code = match.group(2)  
station_code = match.group(3)

In the code above, phone should be ‘123–456–7890’ since we passed in nothing to group. Passing in 0 also returns the same thing.

area_code should be '123' since we passed in 1 to group , which returns the first group match.

exchange_code should be '456' since we passed in 2 to group , which returns the 2nd group match.

Finally, station_code should be '7890' since we passed in 3 to group , which returns the 3rd group match.

If we want to pass in parentheses or any other special character as a character of the pattern rather than a symbol for the regex, then we have to put a \ before it.

Matching Multiple Groups with the Pipe

We can use the | symbol, which is called a pipe to match one of many expressions.

For instance, we write the following to get the match:

import re  
name_regex = re.compile('Jane|Joe')  
msg = 'Jane and Joe'  
match = name_regex.search(msg)  
match = match.group()

match should be 'Jane' since this is the first match that’s found according to the regex.

We can combine pipes and parentheses to find a part of a string. For example, we can write the following code:

import re  
snow_regex = re.compile(r'snow(man|mobile|shoe)')  
msg = 'I am walking on a snowshoe'  
snow_match = snow_regex.search(msg)  
match = snow_match.group()  
group_match = snow_match.group(1)

to get the whole match with match , which has the value 'snowshoe' .

group_match should have the partial group match, which is 'shoe' .

Optional Matching with the Question Mark

We can add a question mark to the end of a group, which makes the group optional for matching purposes.

For example, we can write:

import re  
snow_regex = re.compile(r'snow(shoe)?')  
msg = 'I am walking on a snowshoe'  
msg_2 = 'I am walking on snow'  
snow_match = snow_regex.search(msg)  
snow_match_2 = snow_regex.search(msg_2)

Then snow_match.group() returns 'snowshoe' and snow_match.group(1) returns 'shoe' .

Since the (shoe) group is optional, snow_match_2.group() returns 'snow' and snow_match_2.group(1) returns None .

Conclusion

We can use regexes to find patterns in strings. They’re denoted by a set of characters that defines a pattern.

In Python, we can use the re module to create a regex object from a string.

Then we can use it to do searches with the search method.

We can define groups with parentheses. Once we did that, we can call group on the match object returned by search .

The group is returned when we pass in an integer to get it by their position.

We can make groups optional with a question mark appended after the group.