11  Dependencies

In contrast to some built-in modules such as pathlib and json that we can import directly after installing python, there are third-party libraries that we want to use but need to be first installed, such as numpy and pandas. This libraries are also called “packages”.

These are open-source libraries maintained mostly by voluntary contributions of people of the community – and you can also contribute to them!

They are being actively developed and thus in permanent evolution. In order to avoid compatibility problems and to ensure reproducibility, we might want to specify the exact versions of the packages we use. It turns out that is not an easy problem and the reason why need a package manager.

11.1 Managing dependencies

The current convention to specify dependencies (and other things) in python projects is to use a file called pyproject.toml that looks like this:

[project]
name = "example_package_name"
version = "0.0.1"
authors = [
  { name="Example Author", email="author@example.com" },
]
description = "A small example package"
readme = "README.md"
requires-python = ">=3.10,<3.12"
dependencies = [
    "numpy==1.2.0",
    "pandas<2.0.0",
    "scikit-learn>=1.0,<2.0"
]

The “dependencies” section is the one we care about here. There we list all the third-party libraries that our project requires. Notice that we can specify both exact versions (with “==”) as well as constraints (with “<,>,>=,<=”). In general we don’t want to deal manually with those aspects – that’s the job of a package manager.

Note

The packages usually follow a so-called “Semantic versioning” convention on how to name the versions of the package to avoid compatibility problems. In short: Given a version number MAJOR.MINOR.PATCH.

MAJOR version when you make incompatible API changes
MINOR version when you add functionality in a backward compatible manner
PATCH version when you make backward compatible bug fixes

Read more about that here.

We will use here the package manager uv. You can read the docs for more details, which I strongly recommend since the documentation is pretty good and constantly being updated. To add a dependency we type:

uv add PACKAGE-NAME

For example:

uv add numpy

That will add the dependency to our list as well as updating the “lock” file. Read more about this workflow and managing dependencies here.

To remove a package from the dependencies of our project we do:

uv remove PACKAGE-NAME

For example:

uv remove numpy