I have been using Ruby professionally for more than a decade now. Until recently, I haven’t explored much outside of the Ruby and Rails community. That changed however after I completed a course in Foundations of Data Science. This made me curious about Python and how to build applications using it.
Python and Ruby have many similarities. Both are interpreted, high-level programming languages. Python also has support for Object-Oriented Programming and Functional Programming. In terms of syntax, they have a similar look and feel, aside from some fundamental differences such as Python being indent-driven.
You may find this article to be very similar to the Ruby on Rails guide I posted years ago. This is not accidental since my goal is to introduce Python web application development to someone who is already familiar in the Ruby space.
The very first step is to install Python itself in your computer. I recommend using pyenv to manage your Python versions. pyenv is a Python version manager, like rbenv. In fact, pyenv is a fork of rbenv and is re-purposed for Python. To install pyenv:
curl https://pyenv.run | bash
After installing, update your login shell configuration by adding the following, e.g. in ~/.zshrc
export PATH="/home/user/.pyenv/bin:$PATH" eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)"
Now we are ready to use pyenv to install a specific Python version. But first, we need to install some dependencies so we can compile Python from source:
sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \ libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \ xz-utils tk-dev libffi-dev liblzma-dev python-openssl
Then, we can easily install a Python version, like 3.6.8 in this example:
pyenv install 3.6.8
If you are having trouble installing Python, it could be related to the OpenSSL version installed in your machine.
On Debian stretch (and Ubuntu bionic), libssl-dev is OpenSSL 1.1.x,
but support for that was only added in Python 2.7.13, 3.5.3 and 3.6.0.
To install earlier versions, you need to replace libssl-dev with
libssl1.0-dev. This is being tracked in
Once Python has been installed, you can opt to set the version (e.g 3.6.8) as your global version. This makes the Python executable available to all terminal sessions:
pyenv global 3.6.8
pip is Python’s package manager, like rubygems or npm. If you installed Python, pip should also be available for you. If for some reason it is not installed, you can install it using the guide here.
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py $ python get-pip.py
In Ruby/Rails we use the awesome library Bundler to handle application package management. We manage the packages using a Gemfile, and it gets converted into Gemfile.lock.
pipenv is similar to bundler, but its functionality extends beyond package management in the application. In this article we will use it similar to bundler so it will handle all the application package dependencies. To install pipenv, just use pip!
pip install pipenv
To specify the application packages, pipenv uses a Pipfile. An example is given below:
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
requests = "*"
flask = "*"
python-dotenv = "*"
flask-sqlalchemy = "*"
flask-migrate = "*"
python_version = "3.6"
The packages and the specific version for each is specified in the file. To install the application dependencies, we use:
Which then generates a Pipenv.lock similar to Bundler.
Web Application Framework
Django is one of the most popular Python web application frameworks, similar to Rails in Ruby. In this article however, we will use a more light-weight framework called Flask.
Flask is similar to Sinatra in Ruby, in which the framework provides a bare-bones (but functional) way to build a web application. An advantage to using these kinds of frameworks is its simplicity and build-as-you-need approach. Compare this to full-featured frameworks like Django or Rails that has several libraries and packages built in (even if you do not use them in your application).
Flask will be installed using the Pipfile we discussed earlier so there is no need to install it manually. The entry point in a Flask application is a file called routes.py which handles the app routing (or endpoints). A very basic example on how a Flask app works is by specifying an index or a home page:
from flask import render_template
from app import app
What this means is when the user accesses the root URL (/) or the index (/index), it will render a template called index.html. Template files are placed in a folder called app/templates, and a basic index.html file looks like this:
Database and Migrations
A web application is not complete without a database of some sort, and Python has existing libraries that handle this. In Rails we have ActiveRecord, while Python has SQLAlchemy. Since we are using Flask, then we can use a package called flask-sqlalchemy to provide an easy to use interface to the SQLAlchemy library. SQLAlchemy also serves as an Object Relational Mapper and has adapters for databases such as MySQL, PostgreSQL and SQLite.
In Rails, we create migration files to indicate the new tables and columns that we will need to apply to the database. In Flask, its a bit more magical. With the aid of the flask-migrate library all you need to do is to create your database models and the rest is handled for you.
Initialize the application first to create the migrations folder and supporting files needed for flask-migrate:
flask db init
Now we set up our database models. For example, let’s say we want to create a Users table. First we need to create our model file:
from app import db
id = db.Column(db.Integer, primary_key=True)
timestamp = db.Column(db.DateTime, index=True, default=datetime.datetime.utcnow)
email = db.Column(db.String(256), index=True, unique=True)
You can see here that you can configure each column if it has a uniqueness validation or if it is indexed. In Rails, these column configurations are specified in the migration files instead.
After finishing defining the models, we then run the migrate command:
flask db migrate -m "create user table"
This automatically parses your database models, determines which tables and columns need to be created, and creates a file that will be run using SQLAlchemy. Note that the database schema has not changed yet after you run the migrate command. In our example, this will generate a file in the migrations folder:
To apply the migration to the database, we run the upgrade command:
flask db upgrade
At this point, all schema changes are applied to the database. In Rails, the upgrade command is equivalent to running:
Running the Application
Make sure all of the application dependencies are installed first:
Python uses a concept called Virtual Environments to manage how to run packages in specific applications. For instance, application App1 may have different packages used compared to application App2, and using virtual environments allow them to both run in the same system and not have issues with package loading or dependencies.
To run the application, we will need to start the virtualenv using pipenv:
After the virtualenv is set up, we can now start using the Python packages and run Flask (the web framework we are using):
Now you can access the application in your browser:
That’s it! You should see the Hello World index page that was created earlier. Now you can extend your application and add modules and libraries as needed. As the motto of Flask says:
Web development, one drop at a time.