Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

🖥️ Lecture slides — Session 02 (Fri Oct 2)

What do you need to run your Python code?

To run Python code with the proper dependencies, you define an environment: a version of Python + some packages + versions of those packages.

What are virtual environments?

A virtual environment is an isolated copy of a specific Python interpreter together with specific versions of external libraries.

The answer is: you never install packages “globally”. Each project gets its own environment, declared in a file that lives in the project repository.

The tools of 2026

Several tools manage environments. Here is the map:

We no longer recommend downloading Anaconda: the Anaconda distribution’s licensing changed in 2024 and its default channel now requires a paid license for many institutional uses. miniforge with conda-forge avoids the issue entirely.

pixi: what this book uses

pixi manages environments per project. The environment is declared in pixi.toml, resolved into pixi.lock, and installed under .pixi/ inside the project directory. There is no “activate the right environment” step to forget: pixi run always uses the project’s own environment.

Install pixi itself first (once per machine). On macOS and Linux:

  curl -fsSL https://pixi.sh/install.sh | sh

or, on macOS with Homebrew, brew install pixi. Restart the terminal, then verify:

  pixi --version

On Windows, work inside WSL2 and use the Linux command above; see the setup walkthrough in 1.9.

Start a project:

  pixi init myproject
  cd myproject

Add packages:

  pixi add python=3.12 numpy pandas matplotlib

This edits pixi.toml:

[workspace]
name = "myproject"
channels = ["conda-forge"]
platforms = ["osx-arm64", "linux-64"]

[dependencies]
python = "3.12.*"
numpy = ">=2"
pandas = ">=2.2"
matplotlib = "*"

and writes pixi.lock, which records the exact version and hash of every package (including transitive dependencies) for every listed platform. Commit both files.

Run things inside the environment:

  pixi run python analysis.py
  pixi run jupyter lab

This book itself is built this way: pixi install then pixi run build from the repository root.

Lockfiles are reproducibility. pixi.toml says what you asked for (“numpy, at least version 2”); pixi.lock says what you actually got (numpy 2.5.0, this build, this hash). Someone who clones your repository and runs pixi install on the same platform gets the identical set of packages — next month, or on a cloud machine. The lockfile pins packages per platform: each entry under platforms in pixi.toml gets its own resolved list, so a collaborator on another OS gets the same package versions in that OS’s builds, not a byte-identical environment. Numerical results can still differ slightly across platforms and hardware; 5.1 treats reproducibility as agreement within a stated tolerance for exactly this reason. Pinned environments are the difference between “works on my machine” and a reproducible analysis, and they are the foundation of the workflow practices in Chapter 5.

uv: for pure-Python projects

uv plays the same role for PyPI-only projects, using the standard pyproject.toml:

  uv init myproject
  uv add numpy pandas
  uv run python analysis.py

It writes a uv.lock with the same reproducibility logic. If your project needs conda-forge packages (GDAL, CUDA-enabled PyTorch builds, obspy), prefer pixi.

conda background

You will encounter environment.yml files in many geoscience repositories, so you should be able to read and use them. With miniforge installed:

  conda env create --file environment.yml
  conda env list
  conda activate myenv
  conda deactivate
  conda env remove --yes --name myenv

(With mamba, replace conda with mamba for faster solves.)

Example environment.yml

name: mlgeo
channels:
  - conda-forge
dependencies:
  - python=3.12
  - jupyter
  - matplotlib
  - numpy>=2
  - pandas>=2.2
  - scipy
  - scikit-learn
  - pytorch

pixi can import these: pixi init --import environment.yml.

Freezing a pip environment

The older idiom for recording exact versions in pip-based workflows:

  pip freeze > requirements.txt

which produces pinned entries like

  matplotlib==3.10.0
  numpy==2.2.1
  pandas==2.2.3

This is a flat snapshot, without hashes or platform information — a lockfile’s weaker ancestor. It still works, but for new projects prefer pixi or uv, which maintain the lockfile for you.