Setup#

Ready Python template#

You can clone my handmade python project template, which handles devenv / docker / uv / pre-commit / and code checking github actions.

DSestu/python-project-template

Using UV as a package manager#

https://docs.astral.sh/uv/getting-started/installation/

Installation instructions can also be found in the uv repo.

Basic commands#

Setup a new project with specific python version.

uv init --python 3.12

Then create the virtual environment.

uv venv

You will need to activate the virtual environment.

. .venv/bin/activate

Synchronize the project with the latest version of the dependencies.

uv sync

Add a new dependency to the project.

uv add requests

Add a dependency with extras, eg alternative to pip install fastapi[standard].

uv add fastapi --extra standard

Run a script with updated dependencies.

uv run python -m my_script

Using devenv/direnv to automatically activate the virtual environment#

Install devenv

In short:

sh <(curl -L https://nixos.org/nix/install) --no-daemon

nix-env -iA devenv -f https://github.com/NixOS/nixpkgs/tarball/nixpkgs-unstable

nix-env -i direnv

Install direnv.

Initialise the project#

devenv init

Using more recent versions of packages#

You need to change the devenv.yaml in order to access to more recent versions of packages (this is required for the uv package).

devenv.yaml

inputs:
  nixpkgs:
    url: github:NixOS/nixpkgs/nixpkgs-unstable
  # pinned terraform to 1.5.7, because post 1.6 it's marked 'unfree' (BSL)
  nixpkgs-for-terraform:
    url: github:NixOS/nixpkgs?rev=4ab8a3de296914f3b631121e9ce3884f1d34e1e5

Tuning the devenv shell#

A good starting snippet for devenv.nix that will automatically activate the virtual environment.

{ pkgs, config, inputs,... }:
let
  # pinned terraform, because post 1.6 it's marked 'unfree' (BSL)
  pinned-terraform-nixpkgs = import inputs.nixpkgs-for-terraform { system = pkgs.stdenv.system; };
in
{
  packages = with pkgs; [
    colima # to provide a docker container runtimes
    docker # for docker commands
    uv
  ];

  dotenv.disableHint = true;

  scripts.init.exec = ''
    unset NIX_CC
  '';

  # scripts.start.exec = "uvicorn app.main:app";
  scripts.tests.exec = "pytest tests";
  scripts.itests.exec = "pytest tests_integration";

  # unset PYTHONPATH is necessary to ensure that libraries solely from the virtual environment are used
  enterShell = ''
    unset PYTHONPATH
    . ./.venv/bin/activate
    uv sync
  '';
}

The file above will also ensure support for docker images, but first you will need to run:

colima start

Docker#

By using the devenv/direnv setup above, you will be able to run docker commands without having it installed system-wide.

You will need to make sure that colima is running with the following command:

colima status

If it is not running, you can start it with the following command:

colima start

Starting snippet to use docker with uv#

The following Dockerfile will install the latest version of uv and run the docker_start.sh script at the root of the project.

FROM python:3.12-slim-bookworm

# The installer requires curl (and certificates) to download the release archive
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates

# Download the latest installer
ADD https://astral.sh/uv/install.sh /uv-installer.sh

# Run the installer then remove it
RUN sh /uv-installer.sh && rm /uv-installer.sh

# Ensure the installed binary is on the `PATH`
ENV PATH="/root/.cargo/bin/:$PATH"

WORKDIR /environment

COPY . /environment/

docker-compose.yml

version: '3.8'

services:
  app:
    build: .
    ports:
      - 8008:8008
    volumes:
      - .:/environment
    environment:
      - PYTHONUNBUFFERED=1
    command: sh -c "chmod +x ./docker_start.sh && ./docker_start.sh"

Run the following command to start the container.

docker compose up -d

Docker GUI without Docker desktop#

Portainer community edition is a nice tool to have a docker GUI without the neeed of Docker Desktop.

Installation instructions can be found here.

To use it, you need only need to run the following command.

docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:2.21.0

Then you can access it at https://localhost:9443.