Python Environments on Unity: Mamba, Conda, and Pip
Introduction
Almost every research project on Unity eventually needs Python packages — NumPy, PyTorch, GDAL, rasterio, scikit-learn, you name it. The simple-looking command pip install numpy hides a lot of complexity, and getting it wrong on a shared HPC system can leave you with a broken environment that takes hours to untangle.
This page covers how to manage Python environments the right way on Unity:
✔ Why isolated environments matter, and why “I’ll just install it globally” is a trap ✔ Why mamba is much better than plain conda (faster solver, same packages) ✔ How to install mamba on Unity, create environments, and activate them ✔ The dangers of mixing pip with conda — and how to do it safely when you must ✔ How to share a working environment with collaborators on Unity ✔ How to put a reproducible environment spec in a public GitHub repo
Prerequisites: Shell Environment (for .bashrc, PATH, groups, umask) and Persistent Sessions (helpful for long installs).
1. Why Use Environments at All?
You probably could run pip install numpy pandas torch straight into Unity’s system Python — and many newcomers do. Here’s why that’s a bad idea:
- Project drift. Project A needs PyTorch 2.1; Project B needs PyTorch 1.13 for a specific paper’s reproducibility. You can’t have both globally.
- Dependency cascades. Installing one package upgrades half its dependencies, which silently breaks an unrelated piece of code you wrote six months ago.
- No way back. “I installed five things, two of them turned out to be the wrong package, now nothing imports correctly.” Without a clean environment to nuke, recovery is painful.
- Sharing is impossible. When a student joins your project and asks “what versions are you using?”, you have to remember.
- No
sudo. On Unity (and any shared cluster), you can’t install system-wide anyway, so packages end up in~/.local/lib/python3.x/site-packages/, which has its own problems.
Environments solve all of this. An environment is a self-contained directory with its own Python interpreter and its own set of packages. You can have ten of them, you can throw any one of them away, and they don’t interfere with each other.
The standard tool for managing environments in scientific Python is conda (the package manager). And the standard way to use conda in 2025 is via mamba (a fast drop-in replacement for conda’s solver). The rest of this page assumes mamba.
2. Why Mamba Instead of Conda?
conda is a great package manager but historically had one big problem: its dependency solver is slow. For a non-trivial environment with PyTorch, CUDA, GDAL, and friends, you can wait minutes (sometimes tens of minutes) on “Solving environment…” while conda tries to find a compatible set of versions.
Mamba is a drop-in replacement written in C++ that solves the same problem in seconds.
- ✔ Same package format
- ✔ Same channels (conda-forge, bioconda, etc.)
- ✔ Same environment files (
environment.yml) - ✔ Same env directories on disk
- ✔ Mamba and conda can both manage the same environment
The recommendation is: install mamba once, then use mamba everywhere instead of conda. Anything you’ve seen documented as conda install X just becomes mamba install X.
3. Installing Mamba on Unity (via Miniforge)
The easiest way to get mamba on Unity is to install Miniforge — a minimal installer that ships with mamba pre-configured and conda-forge set as the default channel.
(In older guides you’ll see “Mambaforge”; that’s the same project under its old name. If you already have a ~/mambaforge/ directory from years ago, leave it — it still works.)
3.1 Download and run the installer
cd ~ # do this in your home directory
wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh
bash Miniforge3-Linux-x86_64.shThe installer asks a few questions:
- Accept the license — type
yes - Install location — accept the default (
~/miniforge3) - Initialize Miniforge3? — type
yes(this edits your~/.bashrc)
Then close and re-open your SSH session (or source ~/.bashrc) so the conda/mamba shell functions are loaded.
3.2 Verify
which mamba # should print something like /home/yourname.##/miniforge3/bin/mamba
mamba --version # prints the mamba version3.3 What the installer added to your .bashrc
It appended the conda/mamba init block described in Shell Environment §8. Don’t delete it — that block is what makes mamba activate work. (Yours will have miniforge3 in place of mambaforge, but the structure is identical.)
3.4 (Optional) Set strict channel priority
Channels are the package repositories conda/mamba pull from. The default after Miniforge install is conda-forge only, which is what you want — it’s the largest community channel and has the most up-to-date versions of scientific packages.
To enforce that only conda-forge is used (preventing accidental mixing with the older defaults channel), run once:
conda config --set channel_priority strictThis avoids subtle dependency-resolution problems caused by packages with the same name living on different channels with different binary builds.
4. Creating and Using Environments
The basic lifecycle:
# Create a new environment with Python 3.11
mamba create -n myproject python=3.11
# Activate it (your prompt prefix changes to show the active env)
mamba activate myproject
# Install packages
mamba install numpy pandas matplotlib
# Run things — Python now points at the env's Python
python -c "import numpy; print(numpy.__version__)"
# Deactivate when done
mamba deactivate4.1 Useful commands
| Command | Effect |
|---|---|
mamba env list |
List all environments on this system |
mamba list |
List packages in the currently active environment |
mamba list -n myproject |
List packages in a specific environment without activating it |
mamba search <package> |
Search conda-forge for available versions of a package |
mamba install <pkg>=<version> |
Pin a specific version |
mamba update <pkg> |
Upgrade one package |
mamba update --all |
Upgrade everything in the active env (use carefully) |
mamba env remove -n myproject |
Delete the environment entirely |
4.2 Activating an environment automatically on login
If you spend 90% of your time in one environment, put this at the end of your ~/.bashrc:
mamba activate myproject(See Shell Environment.) Every new SSH session lands in that environment.
4.3 Activating environments inside Slurm batch scripts
Slurm jobs run a stripped-down non-interactive shell that doesn’t inherit your activated env. Inside myjob.slurm:
#!/bin/bash
#SBATCH --time=04:00:00
#SBATCH --partition=batch
#SBATCH --mem=16G
# Load conda/mamba shell functions, then activate the env
source ~/miniforge3/etc/profile.d/conda.sh
mamba activate myproject
python train.pyThe source ~/miniforge3/etc/profile.d/conda.sh step is the same machinery your .bashrc runs automatically in interactive shells — batch scripts need it explicit.
6. ⚠ Mamba vs Pip — Where Things Go Wrong
This is the most important section on this page. Mixing pip and conda incorrectly is the single biggest source of “my environment is mysteriously broken” tickets in scientific Python.
6.1 What pip and mamba each do
| mamba | pip | |
|---|---|---|
| Package format | Conda packages (.conda/.tar.bz2) |
Python wheels (.whl) and source dists |
| Package sources | conda-forge, bioconda, etc. | PyPI (pypi.org) |
| Can install non-Python deps | ✅ Yes (C libraries, CUDA, GDAL, etc.) | ❌ Python-only, mostly |
| Dependency resolver | Full SAT-solver — checks the whole env is consistent | Greedy per-install — doesn’t re-check other packages |
| Tracks what’s installed | ✅ Yes, in env metadata | ✅ Yes, but separately |
| Can break the env? | Rarely (solver catches conflicts) | Frequently (especially with C extensions) |
6.2 The nightmare scenario
You create a clean env:
mamba create -n myenv python=3.11
mamba activate myenv
mamba install numpy scipy pandasMamba installs NumPy from conda-forge, linked against the conda-forge OpenBLAS for optimized linear algebra. Everything works.
Now you do:
pip install some-niche-packageThat package depends on NumPy, and pip says “Oh, NumPy isn’t installed from my perspective” (because pip and conda track packages separately), and reinstalls NumPy from PyPI — built against a different BLAS, possibly a different ABI version.
Now half your previously-working imports either crash with cryptic linker errors, or worse: silently produce wrong numerical results.
Recovery typically means nuking the environment and starting over:
mamba deactivate
mamba env remove -n myenv
mamba create -n myenv python=3.11 ... # redo, more carefully this time6.3 ✅ Rules for safely mixing pip and mamba
If a package you need really isn’t available on conda-forge, follow these rules:
- Install everything mamba can provide FIRST, in one
mamba install(or oneenvironment.yml). - Only after that, install pip-only packages with
pip install --no-deps <package>— the--no-depsflag is critical, because it tells pip not to “fix” packages that conda already installed. - Never
pip install --upgrade <something-conda-installed>— pip will gleefully overwrite the conda-managed copy with an incompatible version. - Check
mamba listafterwards — packages installed via pip show up with apypichannel marker, so you can see what’s tracked where.
8. Lock Files for True Reproducibility (conda-lock)
When you need an environment that recreates exactly — same versions, same builds, same hashes — use conda-lock.
8.1 Install conda-lock
mamba install -n base conda-lock # one-time, install into base env8.2 Generate a lock file
Starting from your environment.yml:
conda-lock lock -f environment.yml --platform linux-64This produces conda-lock.yml with every package pinned to a specific build + hash:
package:
- name: numpy
version: 1.26.4
build: py311h64a7726_0
sha256: 1d2bf6...
...8.3 Recreate from the lock file
conda-lock install --name myproject conda-lock.ymlSame versions every time, regardless of when you run it.
8.4 When to bother
- ✅ Paper code that needs to reproduce results
- ✅ Sharing with reviewers who must run your code as you ran it
- ✅ Deploying the same env on multiple compute nodes
- ❌ Your day-to-day exploratory work — the rigidity is annoying
9. Putting an Environment Spec in a Public GitHub Repo
When your project goes public (paper code, lab tool, tutorial repo), the right artifacts to commit:
✔ DO commit
environment.yml— the human-readable, loosely-pinned specconda-lock.yml(or platform-specific*.conda-lock.yml) — for exact reproducibility- A
READMEsection explaining how to recreate the env. For example:
## Setup
Install [Miniforge](https://github.com/conda-forge/miniforge), then:
```bash
mamba env create -f environment.yml
mamba activate myproject
```
For exact reproduction of the published results:
```bash
conda-lock install --name myproject conda-lock.yml
```❌ DON’T commit
- The env directory itself (
envs/myproject/) — hundreds of MB to GB, platform-specific binaries, useless to others ~/.condarc— may contain tokens for private channels~/.pip/pip.conf— same reason__pycache__/,.ipynb_checkpoints/, etc. — the usual Python noise
A sensible .gitignore snippet for a Python project
# Conda / mamba envs
envs/
*.conda-lock.yml.bak
# Python noise
__pycache__/
*.pyc
.ipynb_checkpoints/
.pytest_cache/
.mypy_cache/
# Local data dumps you don't want public
data/raw/
*.h5
*.npy
# Secrets
.env
.secrets
10. Using Your Mamba Env in Jupyter
If you ran Jupyter via OnDemand or an SSH tunnel and your notebook needs myproject’s packages, you need to register the env as a Jupyter kernel once:
mamba activate myproject
mamba install ipykernel # if not already installed
python -m ipykernel install --user --name myproject --display-name "Python (myproject)"Then refresh Jupyter and select “Python (myproject)” from the Kernel menu.
To list installed kernels:
jupyter kernelspec listTo remove one:
jupyter kernelspec remove myproject11. Common Pitfalls
❌ “command not found: mamba”
Either:
- You haven’t
source ~/.bashrc’d since installing — open a new shell - The init block didn’t make it into
.bashrc— re-run~/miniforge3/bin/mamba init bash
❌ “Solving environment: failed” — even with mamba
You’ve asked for an impossible combination (e.g. two packages that pin conflicting versions of the same dep). Mamba’s error message usually shows the conflict — read it. Sometimes the fix is loosening a pin; sometimes it’s adding conda-forge if you’ve accidentally fallen back to the defaults channel.
❌ “ModuleNotFoundError: No module named ‘mypackage’” right after activating
You may have a different python on your PATH that’s winning over the env’s Python. Run which python — it should point at ~/miniforge3/envs/myproject/bin/python (or the path-based equivalent). If not, check .bashrc for stale PATH=... lines that prepend the wrong directory.
❌ “Disk quota exceeded” — conda envs eating my home directory
mamba clean -a # clean caches, tarballs, indexes
du -sh ~/miniforge3/envs/* # which envs are biggest?
mamba env remove -n old_unused_envFor lab-wide installs, consider creating envs under /fs/project/<group>/envs/ (Section 5) where the storage quota is much larger.
❌ Pip install broke my env
See Section 6.2. Easiest fix: mamba env remove -n broken_env && mamba env create -f environment.yml. (And next time, install everything mamba can provide first, then pip install --no-deps.)
❌ “Conda is configured to use the channel pkgs/main …”
You’ve been hit by Anaconda’s default channel showing up. Mitigation:
conda config --remove channels defaults
conda config --add channels conda-forge
conda config --set channel_priority strict❌ Jupyter “kernel won’t start” after env update
Reinstall the kernel:
mamba activate myproject
python -m ipykernel install --user --name myproject --display-name "Python (myproject)" --force12. Quick Reference
Setup (once):
wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh
bash Miniforge3-Linux-x86_64.sh
source ~/.bashrc
conda config --set channel_priority strictPer-project:
mamba create -n myproject python=3.11 numpy pandas matplotlib
mamba activate myproject
mamba env export --from-history > environment.ymlShared lab env:
mamba create -p /fs/project/<group>/envs/sharedenv python=3.11 ...Recreate from a spec:
mamba env create -f environment.ymlLock for reproducibility:
conda-lock lock -f environment.yml --platform linux-64
conda-lock install --name myproject conda-lock.ymlPip the right way:
# AFTER all mamba installs are done:
pip install --no-deps some-pypi-only-package13. Summary
- ✔ Use mamba, not
conda(same packages, dramatically faster) - ✔ One environment per project — never install into the system Python
- ✔ Install via Miniforge (
conda-forgechannel by default) - ✔ For lab-shared envs, use
-p /fs/project/<group>/envs/<name>+umask 002 - ⚠ Mixing pip and conda is dangerous — mamba first, then
pip install --no-deps - ✔ Export with
mamba env export --from-history > environment.ymlfor sharing - ✔ Use
conda-lockwhen you need exact reproducibility (papers, reviewers) - ✔ Commit
environment.yml(and optionallyconda-lock.yml) to your public repo; don’t commit the env directory - ✔ Register your env as a Jupyter kernel for notebook work
Back to Shell Environment for the .bashrc patterns, or onward to the Slurm section for running your env’s code on the cluster’s compute nodes.