Around a year ago, I read one of the more influential articles about Python I’ve ever read: Hypermodern Python.
That article introduced many new tools to me and changed some of my thinking about programming in Python.
A year later, after experiencing many of the tools listed in the article, I feel comfortable sharing my impressions.
You don’t have to read the original article to follow this short blog post, but I strongly recommend it:
- The original article includes many useful Python tools and frameworks.
- It touches on some theories and best practices.
- It’s a step-by-step coding tutorial, allowing you to experience and explore the various tools freely.
- On top of that, there are additional references to tools that are not covered in the article itself, so you can expand your knowledge even further.
- Finally, it’s split into several sections, making it easy to follow.
Here are the main tools and frameworks from the article, and an extra few of my own:
Poetry is by far the best dependency resolution mechanism for Python I have used to date.
Its approach to dependency management is simple:
- You define your direct dependencies, with general version constraints.
- Poetry resolves the dependencies, finding exact versions for the packages to meet all constraints. This includes derived packages recursively.
- All of your packages, including direct and derived dependencies, are fixated and their versions are recorded and stored in
- Whenever you, a fellow developer, or a build machine, tries to install the dependencies, it uses the
poetry.lockfile to ensure exact versions for all the direct and derived packages, leading to a deterministic build and uniformity across the entire project.
Pyenv is a great way of installing local versions of Python, dedicated to specific projects, without impacting the whole system.
It’s also a great way of defining your python version explicitly, removing ambiguity, and helping to create uniformity in your project.
This uniformity will reduce the likelihood of bugs caused by developers having a different Python version than the one deployed in production.
Its main idea is to use Python code to specify the various virtual environments, unlike its predecessor tox, which uses configuration files/scripts.
Personally, I think that Nox is a step in the wrong direction: the build process should be simple and straightforward. Using code during your build is a potential opening to complex functionality and bugs.
Since I didn’t like Nox but had to have entry points for the build process, I had to find an alternative. That alternative is Makefiles, which are described in the section below.
GNU make, aka Makefile
Makefiles were not mentioned in the original article, but they integrate nicely with Poetry to provide a better coding experience.
Makefiles date before Python, they have allowed developers to build their software for over 40 years now (!!!).
Some developers find them archaic. I had a similar notion in the past. But now, I strongly believe that Pyenv + Makefiles + Poetry is superior to tox/Nox. Makefiles allow a standard, simple and resilient build process, which is exactly what you want of your build process.
I covered the problems with Nox in the previous section, now let’s focus on tox’s disadvantages:
- At the core of tox are the environments: every entry point has a separate environment, which is cached for performance. The main disadvantage of this approach is that environments become stale and have to be manually updated by developers. This causes unexpected behavior: the code might pass on one environment, but fail in another environment on the same computer, a fellow developer’s computer, or on a build machine. This wastes a lot of time.
- Other benefits of tox, like the ability to test your code on different Python versions, can be achieved with other modern tools, making tox less appealing nowadays.
- So we are left with tox’s ability to have entry points — but you can have those easily with Makefiles.
pre-commit is a “framework for managing and maintaining multi-language pre-commit hooks”, a simple statement that gets the gist of it.
This framework allows you to add scripts on certain git events like before every commit/push. The scripts are usually around code verification.
A common use case is to add style checks before commits. This way you can ensure that:
- Your code looks the same
- Speed up development cycles by providing the developers a quicker, local feedback loop instead of a slower, remote CI pipeline.
pyproject.toml is defined in PEP 621. Its purpose is to store your project’s metadata in a single place. It’s super convenient and useful, allowing quick installation, setup, and onboarding for developers.
It plays nicely with Poetry and other common tools, although some tools don’t support it yet.
The sections above cover most of my thinking about Hypermodern Python, there are additional tools and frameworks mostly around Code Style, Linting and Formatting, Type Checking, etc. which I did not cover here. Those deserve a post of their own.
If you want to experience the Hypermodern Python approach, you can create a new preconfigured project in seconds, using this cookie cutter.