Perfect Python Environment

Perfect Python Environment

Greetings! This post shows step by step the installation and configuration of all the tools needed to set up an agile and robust Python development environment. It is assumed that the text editor to be used will be VSCode and that the environment will be running on a Debian/Ubuntu based Linux system (including WSL).

Managing multiple Python versions

Not all projects will always be developed on the same version of Python. Sometimes we will need Python 3.9, sometimes Python 3.12... That is why it is very important to be able to move between versions and migrate them easily.

This is where PyEnv comes into play, a tool that allows precisely this: to install and switch from one Python version to another with ease. For its installation we can use their official installer:

curl https://pyenv.run | bash

Once we have it installed, it is necessary to add the pertinent variables to our Shell, something that can be done in a simple way following its official documentation.

Finally, it is necessary to install a Python version of our choice and set it as the global default version:

pyenv install 3.8.10
pyenv global 3.8.10

This concludes the installation of PyEnv. Whenever we need a new version of Python on our system, we can install it with the command pyenv install.

Installing global and isolated Python packages

To install some of the tools needed in this environment, it will be necessary to have Python applications that run globally. To avoid any conflicts, the best way to install these tools is in isolation. For this purpose, the pipx tool that perfectly fulfills this task.

Installation is quite simple:

  • For Ubuntu 23.04 or above:
sudo apt update
sudo apt install pipx
pipx ensurepath
  • For Ubuntu 22.04 or below (you need to have a global Python versions installed with PyEnv!):
python3 -m pip install --user pipx
python3 -m pipx ensurepath

Installing and using Poetry, our project manager

Installation

Since we have installed pipx, the installation of Poetry is very simple:

pipx install poetry

After installing Poetry, we need to configure it to be able to read the current version of Python from PyEnv. Just run the above command:

poetry config virtualenvs.prefer-active-python true

Reading dotenv file

Poetry does not include native support for reading .env files and loading environment variables, something that other tools such as Pipenv do. To solve this, there is the poetry-dotenv-plugin. Its installation in our Poetry environment is simple:

poetry self add poetry-dotenv-plugin

Creating a Poetry project

To start our Poetry project, we must first make sure that we have the desired Python version installed in PyEnv, switch to it and start the new project:

pyenv install 3.12.0
pyenv local 3.12.0

poetry new your-project
cd your-project
poetry install

With this, we will have the initial structure of a project with the desired Python version. We can check the environment being used with the following command:

poetry env info

This should return an output similar to:

Virtualenv
Python:         3.12.0
Implementation: CPython
Path:           /home/marcos/.cache/pypoetry/virtualenvs/test-F5kZevV3-py3.12
Executable:     /home/marcos/.cache/pypoetry/virtualenvs/test-F5kZevV3-py3.12/bin/python
Valid:          True

System
Platform:   linux
OS:         posix
Python:     3.12.0
Path:       /home/marcos/.pyenv/versions/3.12.0
Executable: /home/marcos/.pyenv/versions/3.12.0/bin/python3.12

Linting and formatting your code

Once we have the initial structure of the project, we should not start programming until we are sure that our code will be coherent, readable and follow the official style guides.

To achieve this, I have chosen to use ruff. This tool is both a linter and a formatter, being extremely fast because it is programmed in Rust.

This tool must be installed in each of the projects in which we want to use it, as a development dependency:

poetry add ruff -D

Although we have the pyproject.toml file to configure our project and dependencies, and ruff is very customizable, we will leave the default options that work very well.

VSCode with ruff

To set ruff as our formatter in VSCode and not have to use its command line, we must:

  1. Download the Astral Software ruff extension from the VSCode store.
  2. Set ruff as our default Python formatter. This can be done at the user or workspace configuration level (.vscode/settings.json):
"[python]": {
        "editor.defaultFormatter": "charliermarsh.ruff"
},
  1. Activate the "editor.formatOnSave" option so that the current file is automatically formatted every time we save.

This way, we will have both the formatter and linter from ruff running in our workspace, with perfect integration with VSCode. If you prefer to use another linter/formatter, ruff allows you to disable these features from the pyproject.toml file.

Ensuring consistent typing

When programming, in order to ensure type consistency throughout the entire code flow and to avoid errors, it is very useful to use strong typing. This is especially important in languages such as Python, which by default are very flexible in this respect.

To obtain this typing consistency, we will use the mypy tool. Installing it is as easy as installing ruff, and we will have to do it in each of the projects in which we want to use it:

poetry add mypy -D

Once installed, we will activate its strict configuration. This configuration, although it may cause more errors and take more time to correct them, is the most robust. To activate it, we must add the following section to the pyproject.toml file:

[tool.mypy]
strict = true
VSCode with mypy

To integrate mypy into VSCode and receive this typing error report in the interface, we must follow the steps below:

  1. Install the Matan Gover mypy extension from the VSCode store.
  2. In the extension configuration, we must enable the option "Mypy: Run Using Active Interpreter".

Final thoughts

Following these steps, we get what for me is being the Python programming environment that I am enjoying using the most and that has generated more efficiency when working on my projects.

As always, everyone has their own tools and methodologies, and any of the components described here are open to improvement.

If you want to further improve the way you do your Python projects, I recommend that you learn more about the pyproject.toml file, for example through this article.