Python#
New concept under development
We are rolling out this approach to handling python packages. We might have to adjust details based on user feedback, so keep an eye on these pages.
We recommend that you build and manage your own Python environment. It is reproducible, it is under your control, and you can add packages to it as you need.
The three tools we support for this are:
pixi – packages from conda-forge
micromamba – packages from conda-forge
Quick start
No preference yet? This gets you a Python interpreter with a typical analysis stack:
cd ~/my_awesome_project
wget -nc https://dkrz-sw.gitlab-pages.dkrz.de/python-envs/specs/km-scale/pyproject.toml
uv run python
Want a Jupyter kernel instead of a normal
python in the shell? Just extend the uv run python line a bit, and it’s
good for use in our Jupyterhub (you might need
to reload in your browser).
uv run python -m ipykernel install --user --name my-kernel --display-name="My Kernel"
Add packages with the tool that built the environment – uv add, pixi
add or micromamba install – never with pip, see why that
breaks things for details.
Create your environments on the /home file system (the default for all three tools), not on /work. They
consist of a huge number of small files, and creating an environment, starting
Python and importing packages are all considerably faster on /home –
see why, and what counts against your quota.
If you need GPU-enabled packages, there is an extra step – the conda-based tools need to be told which CUDA version
to target, since Levante’s login nodes have no GPU to detect it from. For
dask and mpi4py, see our parallel-Python guide – mpi4py in particular needs a rebuild against
Levante’s own MPI, since neither the PyPI nor the conda-forge version speaks
the PMIx interface Slurm uses here.
The system wide python3 modules still exist, but they are frozen and no
longer updated. You can keep using them in existing workflows, but we recommend
switching to your own environments built with one of the tools above –
more on those further down.
Choosing a tool#
No strong preference? Use uv – it is the fastest to set up and needs no
extra configuration for GPU-enabled packages.
Note
Pick one and stick with it. Each tool keeps its own package cache, so
using all three costs three times the /home quota for largely the same
packages. If you do switch, clean up the cache of the tool you left behind,
see where those caches live.
tool |
packages from |
environment location |
lockfile |
use when |
|---|---|---|---|---|
|
PyPI |
|
|
your stack is pure Python, you want the fastest option, or you want GPU-enabled packages without extra configuration |
|
conda-forge |
|
|
you need packages that only exist on conda-forge |
|
conda-forge |
named environment under a root prefix |
none |
you want global, named environments |
uv and pixi write their lockfile next to your project and pin every
resolved package, so you and your colleagues can rebuild the exact same
environment later – keep it under version control. micromamba has no
lockfile: an environment.yaml is re-resolved on every install and may well
give you different versions each time. See the uv and pixi documentation for what
lockfiles contain, and the specification file documentation
for the closest micromamba equivalent.
Ready-made environments#
Before you assemble your own package list, have a look at https://dkrz-sw.gitlab-pages.dkrz.de/python-envs/. It publishes curated specifications for the typical DKRZ analysis stack (xarray, dask, intake, healpix, easygems, cartopy, …).
Every specification is built and its workloads are tested with all three installers on Levante on a daily basis. The page shows the resulting pass / fail matrix. Specifications that can make use of a GPU node on Levante are marked in the GPU column.
Two files are published per environment: the conda environment.yaml and an
auto-converted pyproject.toml. Download the one your tool needs:
SPEC=km-scale # pick a specification from the page above
BASE=https://dkrz-sw.gitlab-pages.dkrz.de/python-envs/specs/$SPEC
# uv
wget -nc $BASE/pyproject.toml
uv sync
# pixi
wget -nc $BASE/environment.yaml
pixi init --import environment.yaml
# micromamba
wget -nc $BASE/environment.yaml
micromamba create -f environment.yaml
The specifications are maintained at https://gitlab.dkrz.de/dkrz-sw/python-envs. Have a look there if you want to contribute a specification; for installing an environment the download above is all you need.
Building your own environment#
All three examples below name a Python version. That is deliberate – see the pinning section for why it matters.
Using uv#
uv init --python 3.13 my_project
cd my_project
uv add xarray dask
uv run python
uv can also install the interpreter itself, independently of any module:
uv python install 3.13
Using pixi#
pixi init my_project
cd my_project
pixi add python=3.13 xarray dask
pixi run python
pixi shell # to get a shell with the current environment in the PATH
Add python yourself, as in the example: a fresh pixi project contains no
interpreter at all.
Using micromamba#
If you know conda, this will feel familiar: same verbs (create,
activate, install, list, env remove), same conda-forge
packages – just faster, and without conda’s own paid-channel footgun. There
is no plain conda/mamba on your default PATH – only a module
provides those – so micromamba is the standalone replacement.
Once per account, add the shell hook:
micromamba shell init --shell bash # adjust to your shell if needed.
Then create and use environments:
micromamba create -n my_env python=3.13 xarray dask
micromamba activate my_env # puts the environment into the PATH
micromamba install netcdf4
python
Unlike the other two tools, micromamba does not put the environment next to
your project: named environments live under $MAMBA_ROOT_PREFIX, together
with the package cache, see the file-system section.
Note
micromamba shell init writes the hook to ~/.bashrc, which bash reads
in interactive non-login shells only. If micromamba activate is not
available in your login shells, see why;
for batch jobs, where it is never available, see the section below.
Using your environment#
The uv and pixi commands below assume you are in your project
directory; micromamba commands name the environment explicitly and work
from anywhere.
To activate an environment in your interactive shell:
source .venv/bin/activate # uv, in your project directory
pixi shell # pixi, in your project directory
micromamba activate my_env # micromamba
Editors and IDEs usually want the path of the interpreter instead. Ask the tool rather than guessing, then paste the result into your editor’s Python interpreter setting:
uv run which python
pixi run which python
micromamba run -n my_env which python
To update the packages in an environment:
uv lock --upgrade && uv sync
pixi update
micromamba update -n my_env --all # WARNING: This will break pinnings you had in your environment.yaml file.
To rebuild somebody else’s environment exactly as they had it – this is what the lockfile is for, and it is the answer to “can I have the same environment as you”:
git clone <repository> && cd <repository>
uv sync --frozen # uv
pixi install --frozen # pixi
Registering a Jupyter kernel#
An environment and a Jupyter kernel are two different things:
The environment is the actual installation: a Python interpreter together with all its packages, in a directory on disk. This is what you use on the command line and in batch jobs, and it is what everything above creates.
A kernel is just a registration that tells Jupyter which interpreter to start for a given name / label. It contains no packages of its own, it only points at an environment.
Install ipykernel into the environment, then run the registration with that
environment’s interpreter:
# uv, in your project directory
uv add ipykernel
uv run python -m ipykernel install --user --name my-kernel --display-name="My Kernel"
# pixi, in your project directory
pixi add ipykernel
pixi run python -m ipykernel install --user --name my-kernel --display-name="My Kernel"
# micromamba
micromamba install -n my_env ipykernel
micromamba run -n my_env python -m ipykernel install --user --name my-kernel --display-name="My Kernel"
--name is the internal name of the kernel, --display-name is the label
shown in JupyterHub. Neither has to match the name of the environment, but
keeping them recognisable helps. My Kernel can then be selected at
https://jupyterhub.dkrz.de, which is available to all users who may submit batch
jobs; reload the browser tab if the kernel does not show up yet.
Because the kernel only points at the environment:
Packages you install into the environment later are available in the kernel right away, just restart the kernel. You do not have to register it again.
If you delete, move or rename the environment, the kernel entry stays behind and will fail to start. Use
jupyter kernelspec listto see your kernels andjupyter kernelspec remove my-kernelto clean up.
See our JupyterHub documentation and its kernels page for details.
Using an environment in a batch job#
A batch script runs in a shell that is neither interactive nor a login shell,
so it reads neither ~/.bashrc nor ~/.bash_profile, see why. Slurm does pass the environment variables
of your submitting shell into the job; micromamba activate is a shell
function instead, and those are not passed along (yes, there are exceptions).
This is the most common reason for jobs failing with command not found
or picking up the wrong Python.
For a job that runs a single Python process, let the tool start it:
cd /home/x/xz0123/my_project
uv run python my_script.py
# or
pixi run python my_script.py
# or
micromamba run -n my_env python my_script.py
If you really need the environment activated in the job script, load the shell hook first:
eval "$(micromamba shell hook -s posix)"
micromamba activate my_env
python my_script.py
Parallel jobs#
Do not put uv run, pixi run or micromamba run behind srun.
Each of the tasks would start its own copy of the tool, and they then contend
for the same lockfile – with micromamba the job can stall on
Cannot lock '~/.cache/mamba/proc'. Resolve the interpreter once, before
srun, and let Slurm start it directly:
cd /home/x/xz0123/my_project
PY=$(uv run which python) # uv
# PY=$(pixi run which python) # pixi
# PY=$(micromamba run -n my_env which python) # micromamba
srun -n 4 $PY my_script.py
This is what you want for mpi4py as well, but note that mpi4py needs an
environment built specifically for Levante, see our parallel-Python
guide.
Pinning the Python version#
Without a version you get whatever your tool considers newest at the time, so which Python you work with becomes a side effect of when you happened to create the environment. How much that matters later differs per tool:
uv init --python 3.13records the version twice: as a lower bound inrequires-pythoninpyproject.toml, and as the exact request in.python-version. Keep the latter under version control – it is the only one of the three files that names a specific interpreter, sinceuv.lockis universal by design and stays valid across a range of Python versions. Without it,uvuses any compatible interpreter it finds, which on Levante can be newer than the one you asked for.uv python pinchanges it later, but does not adjustrequires-python.pixiwrites your request intopixi.toml, andpixi.lockthen records the interpreter like any other conda package – so a colleague runningpixi install --frozengets exactly your Python. Do addpythonexplicitly, though: if it only arrives as a dependency of something else, it comes in unpinned and nothing inpixi.tomlsays which version you got.micromambahas no lockfile, so the version in yourcreatecommand orenvironment.yamlis the only record. Without it, every re-creation resolves afresh.
File system, quota and caches#
Keep your project on ``/home``. All three tools link packages out of a
package cache instead of copying them, and these links cannot cross file
systems. Since uv puts .venv/ and pixi puts .pixi/ next to your
project, a project on /work ends up with its environment on a different file
system than its cache: the tools silently fall back to full copies, which is
slower and uses more space. The same applies to micromamba environments
outside $MAMBA_ROOT_PREFIX.
Environments and package caches both count against your /home quota, see
the file-systems page for the current value and
for the quota command to check your usage.
The default locations are already on /home: ~/.cache/uv for uv,
~/.cache/rattler/cache for pixi, and $MAMBA_ROOT_PREFIX/pkgs for
micromamba, whose prefix defaults to
~/micromamba. So there is nothing you need to change. To find out what is
eating your quota, ask the tools rather than guessing, and check every path
they print, as there may be more than one:
uv cache dir
pixi info # see 'Cache dir'
micromamba info # see 'package cache'
If you do move a cache, keep it on /home for the reason above. See uv (UV_CACHE_DIR) and pixi
(PIXI_CACHE_DIR). For micromamba, move MAMBA_ROOT_PREFIX instead of
the cache alone: named environments and the package cache both live under it, so
moving the prefix takes both along and cannot split them across file systems.
pixi will warn on every run that its repodata and
conda-pypi-mapping caches sit on a network file system and redirect them to
/tmp for that run. That is fine and needs no action: it concerns metadata
only, not the package cache your environments are linked from. Set
netfs-redirect = "never" under the [cache] table in pixi’s config.toml if you would
rather not see it.
Reclaiming space#
Delete environments you no longer need:
rm -rf .venv # uv, in the project directory
pixi clean # pixi, in the project directory
micromamba env remove -n my_env
Cleaning a cache never breaks an existing environment – the environment holds
hard links to those files, so the only thing you lose is a re-download later.
uv and micromamba can drop just the unused entries:
uv cache prune
micromamba clean -p
pixi has no equivalent: its cache is cleaned by type, not by usage, so
pixi clean cache --conda (where the package files are) is the closest thing.
To wipe a cache completely:
uv cache clean
pixi clean cache
micromamba clean -a
Pitfalls#
Do not use pip#
We often see users who add custom Python packages on top of an existing
environment with pip. Add them with the tool that built the environment
instead – uv add, pixi add or micromamba install. Using pip
causes trouble both inside and outside an environment, for two different
reasons.
Inside an environment, the tools do not know what pip put there, so the
next uv sync, pixi install or micromamba install may remove or break
it, and the environment no longer matches its specification. For packages that
exist on PyPI only, pixi has pixi add –pypi; micromamba has no
equivalent, list those in the pip: section of your environment.yaml so
that they are at least part of the specification.
Outside an environment, typically with pip install --user, the packages end
up in your home directory in ~/.local/lib/python*. These paths take
precedence over the packages installed in a conda-based environment, so pixi
and micromamba environments – and the system wide python3 modules –
can all pick them up. Sometimes this works, but in many cases an incompatible
package version gets loaded and produces hard-to-debug errors that nobody else
can reproduce. Environments created by uv are not affected, as they ignore
~/.local entirely.
Usually we recommend to remove such installations by simply deleting
~/.local/lib/python*. Note that this also removes packages that were not
conflicting, and may therefore break other workflows. Do this at your own
risk! As a less invasive check, set PYTHONNOUSERSITE=1, which
keeps Python from adding ~/.local to sys.path, and see whether that makes
the problem go away.
None of this applies to a plain virtual environment that you create with python
-m venv and populate with pip yourself: no other tool manages it, so
pip is exactly the right tool there. That is a perfectly good workflow, but
uv installs the same PyPI packages considerably faster and writes a lockfile
while doing so, so we would start a new project with uv. If you already have
one, From pip to a uv project walks you through
turning your requirements.txt into a pyproject.toml and a lockfile.
Package channels and licensing#
Channels are the locations where conda packages are stored. On Levante the
system wide configuration in /etc/conda/condarc already selects the
conda-forge channel, which is free for all to use, and disables the Anaconda
defaults channel. You can read it with cat /etc/conda/condarc. pixi
likewise defaults to conda-forge, which it records in your pixi.toml.
You therefore do not need to pass -c conda-forge yourself.
Warning
Your own configuration overrides the system wide one. Check whether you
already have a ~/.condarc from an earlier setup (cat ~/.condarc):
if you write one now, or install Miniconda or Anaconda, you may end up on a
channel that requires a paid license – you are not allowed to use those
here. In the rare cases where you need to add a channel, please make sure
that its license allows free use for all.
Troubleshooting#
When a program picks up the wrong packages, find out which Python is actually running and where it looks for packages:
which python
python -c 'import sys; print(sys.executable)'
python -m site
echo $PYTHONPATH # should normally be empty
python -m site reports ENABLE_USER_SITE: if it is
True, the user site-packages directory under ~/.local is on sys.path
and its packages can shadow the ones in your environment.
micromamba activate with no environment name activates base, which is
normally empty. With no module loaded, that leaves you with no python at
all, which is easy to spot. If a module like python3/... is still loaded
in the same shell, its bin/ directory is still on PATH, so python
silently keeps resolving there instead, which looks like it worked but did
not. Either way, name the environment explicitly.
If uv add or pixi add fails while compiling a package from source,
that is not necessarily a missing toolchain: Levante’s login nodes have
/usr/bin/gcc on PATH by default, no module load needed. It is a
dated system compiler (GCC 8.5.0), though, so a build that needs a newer
C/C++ standard can still fail on it – module load gcc
for a newer one. Either way this only gives you the compiler itself: MPI,
HDF5 and similar libraries still come from their own modules, see our
parallel-Python guide.
If an import fails immediately after you added the package, check that it
really was added: a rejected uv add can still leave you with a working
environment that simply does not contain the new package.
uv pip list # or: pixi list, micromamba list -n my_env
cat pyproject.toml # or: pixi.toml
If you are stuck, get in touch with our User Support.
Legacy: system wide python3 modules#
Warning
The python3 modules are frozen. They receive no further updates, and we
do not recommend using them for new work.
The modules follow the naming convention python3/YYYY.XX-compilerversion, for example:
module load python3/2023.01-gcc-11.2.0
Always use the full module name to avoid surprises when the default changes.
These environments are CPU-only and do not contain GPU-enabled packages. For GPU support, see the GPU page.
Looking for the same kind of curated, ready-to-use environment going forward?
Our specification catalog publishes
the equivalent, built and tested on Levante every day with uv, pixi
and micromamba.
If you built a personal conda create --name my_env environment on top of
one of these modules, it keeps working. You might want to try a new environment
instead, as new python versions and the use of the home directory can improve
your experience.