I know a little about nix. Not a lot. I know some things about Python virtual environments, asdf and a few things about package managers. I’ve heard the combo of direnv and nix is fantastic from a number of engineers I trust, but I haven’t had the chance to figure out what these tools can really do. I could totally ask someone what their setup is, but I decided to ask ChatGPT (gpt-4) to see what would happen. The following is the summary of what I did that worked, as instructed and summarized by the LM, with a bit of editing and commentary by me.

Creating a Python environment with Nix#

In this example, we will create a Python environment with specific packages (requests and beautifulsoup4) using Nix. We will then use this environment to run a Python script that fetches a web page and prints its title.

Python Script#

Create a Python script named web_title.py with the following content:

import requests
from bs4 import BeautifulSoup

def get_web_title(url):
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')
    return soup.title.string

if __name__ == "__main__":
    url = "https://nixos.org/"
    title = get_web_title(url)
    print(f"The title of the web page at {url} is: {title}")

Nix environment#

Create a Nix expression named python-environment.nix with the following content:

{ pkgs ? import <nixpkgs> { } }:

let
  pythonEnv = pkgs.python3.withPackages(ps: with ps; [
    ps.beautifulsoup4
    ps.requests
  ]);
in
pkgs.mkShell {
  packages = [
    pythonEnv
  ];
}

This Nix expression creates a shell environment with the required Python packages. The withPackages function is used to create a custom Python interpreter that includes the specified packages.

Running the script#

To enter the Nix shell environment, run the following command in your terminal:

nix-shell python-environment.nix

Inside the nix-shell environment, you can run the web_title.py script with:

python web_title.py

This will fetch the web page at https://nixos.org and print its title.

The title of the web page at https://nixos.org/ is: Nix & NixOS | Reproducible builds and deployments

By using Nix, we ensure that the Python environment and its dependencies are managed in an isolated and reproducible manner, without affecting the rest of the system or other projects.

Adding direnv to the environment#

If you don’t have it already, install direnv from here.

Create an .envrc file in the same directory as your python-environment.nix file with the following content:

use_nix
export MY_SECRET_KEY="your-secret-key-here"

Replace "your-secret-key-here" with the actual secret you want to use.

Create a symbolic link named shell.nix pointing to the python-environment.nix file:

ln -s python-environment.nix shell.nix

Allow direnv to load the .envrc file in the current directory:

direnv allow

Now, direnv will automatically load the Nix environment when you enter the directory, and unload it when you leave. Additionally, the MY_SECRET_KEY environment variable will be set with the specified value.

You just have everything there, loaded and isolated when you cd into the project directory.

Inside your Python scripts, you can access the environment variable using the os.environ dictionary:

import os

secret_key = os.environ["MY_SECRET_KEY"]

IMPORTANT: To avoid sharing sensitive information, do not commit your .envrc file to version control

Wrapping it up#

To tie it all together, run the example above, but with direnv you no longer need to run nix-shell python-environment.nix.

Let’s modify the code a little to print the environment variable.

import os
import requests
from bs4 import BeautifulSoup

def get_web_title(url):
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')
    return soup.title.string

if __name__ == "__main__":
    url = "https://nixos.org/"
    title = get_web_title(url)
    print(f"The title of the web page at {url} is: {title}")
    print(os.environ.get("MY_SECRET_KEY"))

Now run it with just:

python web_title.py

Output:

The title of the web page at https://nixos.org/ is: Nix & NixOS | Reproducible builds and deployments
your-secret-key-here

๐Ÿ‘