Skip to main content
Learn how to create Python projects with Pixi, manage dependencies from both conda and PyPI, and leverage the power of reproducible environments.

Why Use Pixi for Python Development?

Pixi builds upon the conda ecosystem, which allows you to create Python environments with all the dependencies you need. This is especially useful when working with:
  • Multiple Python interpreters
  • Bindings to C and C++ libraries
  • Packages that require system-level dependencies
  • Mixed conda and PyPI packages
For example, GDAL from PyPI doesn’t include binary C dependencies, but the conda package does. On the other hand, some packages are only available through PyPI. Pixi gives you the best of both worlds.

Getting Started

1
Initialize a Python Project
2
Create a new Python project using the pyproject.toml format:
3
pixi init my-python-project --format pyproject
cd my-python-project
4
This creates a project with the following structure:
5
my-python-project/
├── pyproject.toml
└── src/
    └── my_python_project/
        └── __init__.py
6
Understand the Project Structure
7
The generated pyproject.toml includes:
8
[project]
name = "my-python-project"
requires-python = ">= 3.11"
version = "0.1.0"
dependencies = []

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.pixi.workspace]
channels = ["conda-forge"]
platforms = ["linux-64", "osx-64", "osx-arm64", "win-64"]

[tool.pixi.pypi-dependencies]
my-python-project = { path = ".", editable = true }
9
The project is installed as an editable dependency, so changes to your code are immediately reflected without reinstalling.
10
Add Dependencies
11
Pixi makes it easy to add both conda and PyPI dependencies:
12
Conda Packages
Add conda packages using pixi add:
pixi add numpy pandas matplotlib
This adds packages to the [tool.pixi.dependencies] section:
[tool.pixi.dependencies]
numpy = ">=2.0.0,<3"
pandas = ">=2.2.0,<3"
matplotlib = ">=3.8.0,<4"
PyPI Packages
Add PyPI packages using the --pypi flag:
pixi add --pypi requests httpx
This adds packages to the [project] dependencies:
[project]
dependencies = ["requests", "httpx"]
With Extras
Install packages with optional extras:
pixi add --pypi "flask[async]==3.1.0"
Result:
[project]
dependencies = ["flask[async]==3.1.0"]

Working with Your Project

Write Python Code

Add a function to src/my_python_project/__init__.py:
from rich import print

def hello():
    return "Hello, [bold magenta]World[/bold magenta]!", ":vampire:"

def say_hello():
    print(*hello())
First, add the rich dependency:
pixi add --pypi rich

Run Your Code

Run your Python code using pixi run:
pixi run python -c 'import my_python_project; my_python_project.say_hello()'
Expected Output:
Hello, World! 🧛
The first run might be slow as Pixi installs dependencies, but subsequent runs will be nearly instant.

Install the Environment

While Pixi automatically installs dependencies when running commands, you can manually install:
pixi install
This creates a .pixi directory containing your isolated environment:
.pixi/
└── envs/
    └── default/

Managing Environments

View Installed Packages

List all packages in your environment:
pixi list
Example Output:
Package          Version     Build               Size       Kind   Source
my-python-project 0.1.0                                     pypi   (editable)
numpy            2.2.1       py313ha4a2180_0     6.2 MiB    conda  numpy
pandas           2.2.0       py313h1f23e1c_0     12.1 MiB   conda  pandas
python           3.13.1      h4f43103_105_cp313  12.3 MiB   conda  python
rich             13.7.0                          789 KiB    pypi   rich-13.7.0-py3-none-any.whl
To see only explicitly installed packages:
pixi list --explicit

Check Dependency Tree

See why a package is installed:
pixi tree pygments
Or see what depends on a package:
pixi tree --invert pygments

Mixing Conda and PyPI Packages

One of Pixi’s powerful features is seamlessly mixing conda and PyPI packages. PyPI packages can depend on conda packages, and Pixi will resolve everything correctly.

Replace PyPI with Conda

If a dependency is installed from PyPI, you can replace it with a conda version:
# Check current source
pixi list pygments
# Output: pygments  2.17.2  pypi

# Add as conda package
pixi add pygments

# Verify it's now from conda
pixi list pygments
# Output: pygments  2.19.1  conda
Your code continues to work without any changes!

Working with Tasks

Create Development Tasks

Define custom tasks in your pyproject.toml:
[tool.pixi.tasks]
start = "python -m my_python_project"
lint = "ruff check ."
format = "ruff format ."
Run tasks with:
pixi run start
pixi run lint
pixi run format

Python Version Management

Specify Python Version

The requires-python field automatically manages the Python interpreter:
[project]
requires-python = ">=3.11,<3.14"
Pixi automatically installs the appropriate Python version - no more brew, apt, or system installation steps!

Use Free-threaded Python

For free-threaded Python (PEP 703), add:
pixi add python-freethreading
Free-threaded Python is experimental and may not work with all packages yet.

Testing Your Code

Create a test file at tests/test_my_project.py:
from my_python_project import hello

def test_hello():
    result = hello()
    assert result == ("Hello, [bold magenta]World[/bold magenta]!", ":vampire:")
Add pytest and create a test environment:
pixi add --pypi --feature test pytest
pixi task add --feature test test "pytest"
pixi workspace environment add test --feature test
Run tests:
pixi run test
Expected Output:
✨ Pixi task (test): pytest
======================== test session starts =========================
platform linux -- Python 3.13.1, pytest-8.3.4, pluggy-1.5.0
rootdir: /path/to/my-python-project
collected 1 item

tests/test_my_project.py .                                     [100%]

========================= 1 passed in 0.02s ==========================

Complete Example

Here’s a complete pyproject.toml for a data science project:
[project]
name = "data-analysis"
requires-python = ">=3.11"
version = "0.1.0"
dependencies = [
    "jupyter",
    "ipykernel",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.pixi.workspace]
channels = ["conda-forge"]
platforms = ["linux-64", "osx-64", "osx-arm64", "win-64"]

[tool.pixi.dependencies]
numpy = ">=2.0.0,<3"
pandas = ">=2.2.0,<3"
matplotlib = ">=3.8.0,<4"
scikit-learn = ">=1.4.0,<2"

[tool.pixi.pypi-dependencies]
data-analysis = { path = ".", editable = true }

[tool.pixi.tasks]
notebook = "jupyter notebook"
lab = "jupyter lab"
clean = "find . -type d -name __pycache__ -exec rm -rf {} +"

[tool.pixi.feature.test.dependencies]
pytest = "*"
pytest-cov = "*"

[tool.pixi.feature.test.tasks]
test = "pytest tests/"
coverage = "pytest --cov=data_analysis tests/"

[tool.pixi.environments]
default = { solve-group = "default" }
test = { features = ["test"], solve-group = "default" }

Best Practices

Use the right package source:
  • Use conda for packages with system dependencies (numpy, scipy, opencv)
  • Use PyPI for pure Python packages
  • Pixi can mix both seamlessly
Leverage editable installs: The editable install means you can modify your code and immediately see changes without reinstalling.
Create multiple environments: Separate development, testing, and production dependencies using features and environments.

Next Steps

Troubleshooting

Slow Installation

The first installation downloads and installs all dependencies. Subsequent installations are much faster due to caching.

Package Conflicts

If you encounter conflicts between conda and PyPI packages, try:
  1. Prefer conda packages when available
  2. Use solve groups to ensure consistency
  3. Check pixi list to see which source each package comes from

Python Version Issues

Ensure your requires-python field matches your dependencies’ requirements:
[project]
requires-python = ">=3.11,<3.14"