Skip to main content

How to start a Python project easily

person drafting on blueprint Photo by Daniel McCullough on Unsplash

I like to try out new technologies and programming languages, and one of the first blockers I face is how to start a project. I absolutely love the way you can start a NodeJS project with npm init. You can do something similar with Python.

In this article, you’ll learn how to start a Python project assuring that its dependencies won’t interfere with other projects' dependencies. And how to use Make to distribute your project to be easily installed in other development machines in no time.

Check your versions

First, check your versions. I’m working with Python 3.10, but this will work with any version of Python 3.

λ python --version
Python 3.10.8

Creating the virtual environment

First, create a folder to store your project.

mkdir ~/Development/python-starter-example
cd ~/Development/python-starter-example

Now, you need to create “the project” itself, aka the virtual environment. The venv module allows you to have all the dependencies and configuration for your Python project inside the project directory, something like NodeJS projects having all the dependencies in node_modules. Let’s do this.

cd ~/Development/python-starter-example
python -m venv env

Working with the virtual environment

Now, the environment is created, but we need to go “inside”, by activating it:

source ./env/bin/activate 

Every time you go back to the project directory, you’ll need to activate it.

How I know that I’m inside the environment?

Easy-peasy: You’ll see a little (env) text in the prompt of your terminal.

Now, every Python command you run inside the environment will be executed in that context, so, if you install a Python library, it won’t interfere with other versions of that library from other python projects.

Installing dependencies

Let’s install Flask, for example:

# (env) => we are inside the environment
pip install flask

The moment of truth: let’s check that Flask was installed inside the environment.

~/Development/python-starter-example
env λ ls env/lib/python3.10/site-packages/flask 
__init__.py	app.py		config.py	globals.py	logging.py	sessions.py	testing.py	wrappers.py
__main__.py	blueprints.py	ctx.py		helpers.py	py.typed	signals.py	typing.py
__pycache__	cli.py		debughelpers.py	json		scaffold.py	templating.py	views.py

So it’s there! But.. what about the Flask binary? Remember that some Python libraries come with a binary you need to execute sometimes. Those binaries will be under the env/bin folder inside your project. See:

~/Development/python-starter-example
env λ ls env/bin                               
Activate.ps1	activate.csh	flask		pip3		python		python3.10
activate	activate.fish	pip		pip3.10		python3

Running the project

Let’s use the example Flask application from its documentation. Create a file called app.py in the project and edit it:

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

Now, run it. Remember that the project need to use the Flask version under the environment:

env/bin/flask --app app run  

* Serving Flask app 'app'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [22/Jan/2023 13:12:24] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [22/Jan/2023 13:12:24] "GET /favicon.ico HTTP/1.1" 404 -

et voilà!

You could also run it directly using the python command. You just need to tweak the code a little.

import os
from flask import Flask

app = Flask(__name__)


@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"


if __name__ == '__main__':
    port = int(os.environ.get('PORT', 3000))
    app.run(host='127.0.0.1', port=port)

Now you can run it with the python command:

~/Development/python-starter-example 10s
env λ python app.py
 * Serving Flask app 'app'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:3000
Press CTRL+C to quit
127.0.0.1 - - [22/Jan/2023 13:16:37] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [22/Jan/2023 13:16:38] "GET /favicon.ico HTTP/1.1" 404 -

Create the requirements file

If you want to distribute your project with the rest of your team, or in a git repository, you need to create the requirements.txt file that will contain all the dependencies that your project’s using. Since you installed everything using pip, the easiest way of creating this file is using the pip freeze command.

pip freeze > requirements.txt

Now you have your requirements file - something like this:

~/Development/python-starter-example
env λ cat requirements.txt            
click==8.1.3
Flask==2.2.2
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.2
Werkzeug==2.2.2

Now that the dependencies are documented in the requirements.txt file, anyone can install them with a simple pip command:

pip install -r requirements.txt

Creating an application runner with Make

Now, let’s automatize it. What if we could create a way of automatically create the virtual env with everything installed in it? I like doing this with Make. Create a file called Makefile inside the project directory and start with this:

.PHONY: all

env/bin/activate: requirements.txt
	python -m venv env
	./env/bin/pip install -r requirements.txt

run: env/bin/activate
	./env/bin/python app.py

freeze: env/bin/pip
	./env/bin/pip freeze > requirements.txt

clean:
	rm -rf __pycache__
	rm -rf ./env

Let’s break down this Makefile. It has three commands:

  • run: will run the app.py Python file if the venv is active. If it’s not it will create the virtual environment and install its dependencies. If no requirements.txt file is found, then nothing will happen.
  • freeze: will update the requirements.txt with all the libraries installed with pip. This is useful if you installed new libraries.
  • clean: will delete the Python cache and the environment. You can use this safely, because if you run your application again, everything will be re-created!

Using Make is really easy, just type make and the command you want to execute, e.g:

make run

Please, not that you need to have make installed. In a mac you can do it with brew (brew install make), in Linux is usually installed or available in the software repositories (apt, dnf…), and in Windows you can use WSL to install a Linux distribution inside Windows and run make from there.

Let’s sum up

In this article, you learned how to create a Python project in its own virtual environment, and also how to create a Makefile to run everything from it. Now, when someone clones that project, they only will need to type make run and it automatically creates the environment, install the dependencies and run the project. Yay!

I hope you found this interesting. Of course this isn’t the only way to manage a Python project. This is the way I use to do it. If there’s something I missed, please, ping me, and I’ll update the article. Thanks!