Nix and direnv
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 requestsfrom 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 ]);inpkgs.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.nixInside the nix-shell environment, you can run the web_title.py script with:
python web_title.pyThis 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 deploymentsBy 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_nixexport 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.nixAllow direnv to load the .envrc file in the current directory:
direnv allowNow, 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 osimport requestsfrom 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.pyOutput:
The title of the web page at https://nixos.org/ is: Nix & NixOS | Reproducible builds and deploymentsyour-secret-key-here👍
Recommended
Using GPT-3.5 to Quickly Generate and Run Shell Commands
I believe that language models are most useful when available at your fingertips in the context of what you're doing. Github Copilot is a well known...
Sandboxed Python Environment
Disclaimer: I am not a security expert or a security professional.
Clean Python Setup
No frills Python projects