Python
With devenv, you get a ready-to-use Python environment — complete with the version you need, a virtual environment, and your preferred package manager. This guide walks you through everything from basic setup to advanced topics like native libraries and Nix-packaged dependencies.
Getting started
To add Python to your project, enable it in your devenv.nix:
This gives you python3 and pip in your shell, using the version of Python that ships with your nixpkgs input.
Choosing a Python version
To use a specific Python version, set the version option:
You can use a major.minor version like "3.11", or pin an exact release like "3.11.3".
Under the hood, this pulls the Python build from nixpkgs-python, which needs to be added as an input in your devenv.yaml:
If you don't need a specific version, you can skip this — devenv uses the default Python 3 from nixpkgs.
Virtual environments
Python projects typically use virtual environments to isolate dependencies. devenv can create and manage one for you:
The virtual environment is stored in $DEVENV_STATE/venv and is activated automatically every time you enter the shell.
If the Python interpreter changes (for example, after updating version), the virtual environment is recreated.
Installing packages from requirements
If your project uses a requirements file, you can point devenv to it. Packages are installed with pip when the shell starts:
{
languages.python = {
enable = true;
venv = {
enable = true;
requirements = ./requirements.txt;
# Or write requirements inline:
# requirements = ''
# requests
# flask>=3.0
# '';
};
};
}
devenv tracks a checksum of your requirements and your Python interpreter, so packages are only reinstalled when something actually changes.
Set venv.quiet = true to suppress pip output during installation.
Changing the project directory
If your Python code lives in a subdirectory rather than the project root, set the directory option:
This changes where devenv looks for files like pyproject.toml, requirements.txt, and poetry.lock.
It also affects where the virtual environment is initialized.
The path can be absolute or relative to the root of the devenv project.
Package managers
devenv integrates with Python package managers to automatically install dependencies when you enter the shell.
Poetry and uv are mutually exclusive
You cannot enable both poetry.install and uv.sync at the same time.
uv
uv is a fast Python package manager that uses pyproject.toml to manage dependencies.
devenv can run uv sync automatically when you enter the shell:
{
languages.python = {
enable = true;
venv.enable = true;
uv = {
enable = true;
sync.enable = true;
};
};
}
This expects a pyproject.toml in your project directory (or the directory set by languages.python.directory).
devenv ensures uv uses the Python interpreter from your configuration rather than downloading its own.
Dependency groups and extras
You can control exactly which dependency groups and extras uv installs:
{
languages.python = {
enable = true;
venv.enable = true;
uv = {
enable = true;
sync = {
enable = true;
allGroups = true; # Install all dependency groups
# groups = [ "dev" "test" ]; # Or pick specific ones
# extras = [ "plotting" ]; # Specific extras
# allExtras = true; # All extras
};
};
};
}
For uv workspaces and additional sync flags, see the options reference below.
Poetry
Poetry manages Python project dependencies and packaging.
devenv can run poetry install and activate the virtual environment for you:
{
languages.python = {
enable = true;
poetry = {
enable = true;
install.enable = true;
activate.enable = true;
};
};
}
This expects pyproject.toml and poetry.lock in your project directory.
Poetry creates its virtual environment in .venv inside your project directory (rather than $DEVENV_STATE/venv).
Install options
You can fine-tune what Poetry installs:
{
languages.python = {
enable = true;
poetry = {
enable = true;
install = {
enable = true;
installRootPackage = true; # Install your project itself
groups = [ "dev" "test" ]; # Specific dependency groups
# ignoredGroups = [ "docs" ]; # Groups to skip
# allExtras = true; # All extras
quiet = true; # Suppress output
};
activate.enable = true;
};
};
}
See the options reference below for the full set of install options.
Using Nix Python packages
Nix can build and cache Python packages, so you don't need to compile them from source or download them from PyPI.
This is especially useful for packages that are difficult to install with pip — like tkinter, or packages with complex native dependencies.
Use withPackages to bundle Nix-built packages into your Python interpreter:
{
languages.python = {
enable = true;
package = pkgs.python3.withPackages (ps: [
ps.numpy
ps.tkinter
]);
venv.enable = true;
};
}
You can combine this with uv or Poetry — the Nix packages provide a base, and your package manager handles the rest. When a virtual environment is active, packages installed by pip/uv/Poetry take priority over the Nix-provided ones.
Native libraries
Some Python packages — like Pillow, grpcio, or transformers — link against native C/C++ libraries at build time. In a Nix-based environment, these libraries aren't in the usual system locations, so pip may fail to find them.
To fix this, add the native libraries to packages:
{
packages = [ pkgs.cairo pkgs.zlib ];
languages.python = {
enable = true;
venv.enable = true;
venv.requirements = ''
pillow
grpcio-tools
'';
};
}
devenv adds these libraries to LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (macOS), and includes the C runtime library automatically.
For more control over library search paths, use the libraries option.
Manylinux support
On Linux, some pre-built Python wheels depend on manylinux compatibility libraries. If you run into related installation errors, enable manylinux support:
Building Python projects with Nix
You can turn your Python project into a reproducible Nix build using uv2nix. This is useful for creating deployable artifacts or integrating with other Nix-based infrastructure:
{ config, ... }:
let
myapp = config.languages.python.import ./path/to/project {};
in
{
languages.python.enable = true;
packages = [ myapp ];
outputs = { inherit myapp; };
}
The project directory must contain a pyproject.toml.
The package name is inferred automatically, or you can set it explicitly with { packageName = "my-custom-name"; }.
Language server
devenv includes Pyright as the default Python language server, enabled automatically.
To use a different language server, or disable it entirely:
{
languages.python = {
enable = true;
# Use a different LSP:
lsp.package = pkgs.python3Packages.python-lsp-server;
# Or disable it entirely:
# lsp.enable = false;
};
}
Putting it all together
Here's a complete example of a Django project using Poetry, with a PostgreSQL database and a dev server managed by devenv:
{ config, pkgs, ... }:
let
db_user = "postgres";
db_name = "myapp";
in
{
languages.python = {
enable = true;
version = "3.11";
poetry = {
enable = true;
install.enable = true;
activate.enable = true;
};
};
env = {
DATABASE_URL = "postgres://${db_user}@/${db_name}?host=${config.env.PGHOST}";
SECRET_KEY = "dev-only-secret"; # Do not use in production
};
services.postgres = {
enable = true;
initialDatabases = [{ name = db_name; user = db_user; }];
};
processes.runserver = {
exec = "exec python manage.py runserver";
after = [ "devenv:processes:postgres" ];
};
}
Options
languages.python.enable
Whether to enable tools for Python development.
Type: boolean
Default:
Example:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.package
The Python package to use.
Type: package
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.directory
The Python project’s root directory. Defaults to the root of the devenv project. Can be an absolute path or one relative to the root of the devenv project.
Type: string
Default:
Example:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.import
Import a Python project using uv2nix.
This function takes a path to a directory containing a pyproject.toml file and returns a derivation that builds the Python project using uv2nix.
Example usage:
let
mypackage = config.languages.python.import ./path/to/python/project {};
in {
languages.python.enable = true;
packages = [ mypackage ];
}
Type: function that evaluates to a(n) function that evaluates to a(n) package
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.libraries
Additional libraries to make available to the Python interpreter.
This is useful when you want to use Python wheels that depend on native libraries.
Type: list of absolute path
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.lsp.enable
Whether to enable Python Language Server.
Type: boolean
Default:
Example:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.lsp.package
The Python language server package to use.
Type: package
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.manylinux.enable
Whether to install manylinux2014 libraries.
Enabled by default on linux;
This is useful when you want to use Python wheels that depend on manylinux2014 libraries.
Type: boolean
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.patches.buildEnv.enable
Whether to apply fixes to Python’s buildEnv for correct runtime initialization:
- Executables use
--inherit-argv0and--resolve-argv0to ensure Python initializes with correctsys.prefixandsys.base_prefix - Python package scripts are unwrapped to invoke the environment’s interpreter directly
Without these fixes, Python may not initialize with the correct prefix paths.
Enabled by default. Newer nixpkgs releases may include upstream fixes that make this patch obsolete.
Type: boolean
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.enable
Whether to enable poetry.
Type: boolean
Default:
Example:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.package
The Poetry package to use.
Type: package
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.activate.enable
Whether to activate the poetry virtual environment automatically.
Type: boolean
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.install.enable
Whether to enable poetry install during devenv initialisation.
Type: boolean
Default:
Example:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.install.allExtras
Whether to install all extras. See --all-extras.
Type: boolean
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.install.allGroups
Whether to install all groups. See --all-groups.
Type: boolean
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.install.compile
Whether poetry install should compile Python source files to bytecode.
Type: boolean
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.install.extras
Which extras to install. See --extras.
Type: list of string
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.install.groups
Which dependency groups to install. See --with.
Type: list of string
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.install.ignoredGroups
Which dependency groups to ignore. See --without.
Type: list of string
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.install.installRootPackage
Whether the root package (your project) should be installed. See --no-root
Type: boolean
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.install.onlyGroups
Which dependency groups to exclusively install. See --only.
Type: list of string
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.install.onlyInstallRootPackage
Whether to only install the root package (your project) should be installed, but no dependencies. See --only-root
Type: boolean
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.install.quiet
Whether poetry install should avoid outputting messages during devenv initialisation.
Type: boolean
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.poetry.install.verbosity
What level of verbosity the output of poetry install should have.
Type: one of “no”, “little”, “more”, “debug”
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.uv.enable
Whether to enable uv.
Type: boolean
Default:
Example:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.uv.package
The uv package to use.
Type: package
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.uv.sync.enable
Whether to enable uv sync during devenv initialisation.
Type: boolean
Default:
Example:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.uv.sync.packages
Sync for specific packages in the workspace. See --package.
Type: list of string
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.uv.sync.allExtras
Whether to install all extras. See --all-extras.
Type: boolean
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.uv.sync.allGroups
Whether to install all groups. See --all-groups.
Type: boolean
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.uv.sync.allPackages
Sync all packages in the workspace. See --all-packages.
Type: boolean
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.uv.sync.arguments
Command line arguments pass to uv sync during devenv initialisation.
Type: list of string
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.uv.sync.extras
Which extras to install. See --extra.
Type: list of string
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.uv.sync.groups
Which dependency groups to install. See --group.
Type: list of string
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.venv.enable
Whether to enable Python virtual environment.
Type: boolean
Default:
Example:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.venv.quiet
Whether pip install should avoid outputting messages during devenv initialisation.
Type: boolean
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.venv.requirements
Contents of pip requirements.txt file.
This is passed to pip install -r during devenv shell initialisation.
Type: null or strings concatenated with “\n” or absolute path
Default:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python
languages.python.version
The Python version to use.
This automatically sets the languages.python.package using nixpkgs-python.
Type: null or string
Default:
Example:
Declared by: - https://github.com/cachix/devenv/blob/main/src/modules/languages/python