1. Introduction
Over the last few years the popularity of Python has grown tremendously in the HPC domain. As a programming language, Python provides significant benefits to HPC scientists [1, 2]––i) Python codes are often simpler to write and understand compared to compiled codes likes C or Fortran, ii) it gives scientists the power of object-oriented programming, iii) application performance can be improved by using lower-level C/Fortran libraries, and iv) scientists can use an abundance of Python libraries to boost their productivity. In recent years, rapid advances in AI/ML and data analytics, and the growth of interactive computing platforms (Jupyter notebooks) have further highlighted the need for Python in HPC. However, despite all its benefits, scientists often find it difficult to manage their Python packages in HPC environments which is a non-trivial problem. The application runtimes and environments on HPC systems are significantly different from personal computers. As a result, support staff at HPC centers have to regularly help scientists troubleshoot their Python installations which leads to loss of productivity [3]. Below we highlight some of the reasons why managing Python packages in an HPC environment is hard.
1.1. Challenges for installing python packages on HPC clusters
In a multi-user environment such as an HPC cluster, users do not have
write access to the root Python installation (also referred to as
base in Python terminology). HPC center staff manage the central
Python installations on these clusters which are typically available to
the users via environment modules. Central installations carry a core
set of packages that are essential for a majority of the users. If users
need to install additional packages, they must do so in a user-writable
location known as a virtual environment. This introduces additional
steps for installing and using Python packages compared to a single-user
setup such as that on a laptop. If the desired package depends on other
libraries, those must be satisfied by loading appropriate modules on a
cluster as opposed to installing them with operating system package
managers such as rpm or apt on a laptop. We observe that documentation
for many scientific packages are written with the assumption that users
have complete control (or root access) over their computers which are
not appropriate for HPC clusters. Fewer packages provide detailed
documentation for non-root installations.
Much like traditional HPC applications, which have a large number of
dependencies, Python packages can also have dependency on many packages.
Packages often rely not only on other Python packages but also on system
libraries and executables. Dependencies can change between versions and
there is no guarantee that all dependencies are explicitly specified in
every package. Although package managers such as pip and conda
perform extensive checks to make sure all dependencies are satisfied, it
is up to the package developers to specify such requirements correctly.
Missing or incomplete dependencies can lead to an unusable package when
installed on an HPC cluster. Moreover, upgrading one or more packages in
an existing installation can break other packages that depend on the
older version.
Apart from these, there are several other reasons which make Python package installation challenging in an HPC environment. Firstly, HPC scientists often need to share their Python installations with colleagues, either for collaborative development or for reproducing simulation results. Sharing a single installation among multiple users can be challenging since each person can have a different environment or initialization scripts in their accounts. Secondly, scientists often use interactive development environments such as Jupyer notebooks for data analysis. But Jupyter installations are centrally managed by HPC center staff, therefore, users cannot install arbitrary packages into the central installation. They must again use virtual environments for installing and managing their Jupyter packages. Thirdly, running large-scale MPI programs with Python is a challenging task. Python accesses a lot of small files during MPI initialization which can lead to IO bottlenecks. Due to this, several HPC centers provide suggestions for reducing IO overhead by using containers or by using an appropriate filesystem [4, 5, 6]. Table 1 summarizes the challenges for installing Python packages on HPC clusters.
1 |
Non-root installation isolated from base Python |
2 |
Package documentation assuming root access |
3 |
Complex dependencies, often on system libraries |
4 |
Frequent package updates |
5 |
Incompatible or missing dependencies |
6 |
Updating packages later can break existing environment |
7 |
Need to share installations with colleagues |
8 |
Need to use custom packages in Jupyter notebooks |
9 |
Filesystem and IO issues for parallel computing |
10 |
Security policy compliance |
Another important consideration for installing Python packages on HPC clusters can be security compliance. For example, some HPC centers may have restrictions on installing binary packages from the internet or they may only allow installation from a trusted repository. In this document, we skip security aspects of Python package installations as security policies may vary significantly among HPC centers.
1.2. State of current HPC Python documentation
We conducted a survey of various HPC centers around the world and looked
at their best practices for managing Python packages. These include
public documentations from national labs in the US
[4, 5, 7, 8],
documentations from university HPC centers
[9, 10], national and international
agencies [6, 11, 12], as
well as official documentations from conda
[13, 14] and pip
[15, 16, 17]. We observe that
the documentations across HPC sites vary quite significantly in terms of
details or their preferred approaches. While most HPC sites recommend
using Anaconda for managing virtual environments and package
installations, some sites explicitly ask users not to use conda.
Some sites also recommend using virtualenv or pipenv for
environment management. Most solutions focus on specific technologies
(conda, pip, pipenv) as opposed to focusing on generic
use-cases that are common in the HPC domain. In this document, we try to
identify common scenarios that HPC scientists face in their quest for
Python dominance and highlight the high-level steps that are needed to
address those. Surprisingly, none of the existing documentations have a
pictorial representation of the steps that users can follow. We present
such a diagram in section 2.1.
The official documentations for conda, pip, and pipenv are
mostly focused on individual developers and can be difficult for
beginners. Some recommendations, although useful for personal computers,
are not applicable to HPC clusters. For example, pip recommends
users to install packages in user mode by using the –user flag which
installs packages in the user’s home directory. However, this is harmful
on HPC clusters when the home directory is shared among multiple
clusters with different architectures. We argue that the inconsistencies
or conflicting messages from different documentations can be confusing
to many users. When users move from one HPC cluster to another, it can
quickly become daunting to remember all the changes they need to follow
to optimize their workflows. We also notice that many of the
configuration steps can either be automated through simple tools or by
providing site-specific Python configurations (such as .condarc or
pip.conf templates). We present more details about such automations
in Section 3. These automations and customizations
are implemented with the conda-env-mod tool developed by the authors
and published on Github [18].
conda-env-mod simplifies the process of environment creation and
environment activation by automating several steps. It can be easily
customized by HPC center staff to incorporate site-specific
recommendations. A previous version of conda-env-mod has been
deployed at several HPC clusters at Purdue university and it has led to
significant reduction in user support requests for Python package
installations [3]. In section
3.6, we present more details of
conda-env-mod and highlight the new features that will be
implemented as part of the BSSw fellowship project in Section
4.
2. Summary of existing documentations
2.1. Common use cases
Based on our survey of Python user guides from various HPC centers, we identified 9 common use-cases that HPC scientists routinely perform. These are listed in Table 1 as frequently asked questions for HPC Python.
How do I install a Python package |
How do I use an installed Python package in my code |
How do I install and use a Python package in Jupyter notebooks |
How do I list the Python environments that I have created |
How do I delete a Python environment that I have created |
How do I list the packages that I have installed |
How do I update a package that I have installed |
How do I share my environment with a colleague |
How do I recreate an existing environment |
We answer each of these questions by highlighting the steps that users
need to perform in Figure 1. At a
high-level, all Python package installations on HPC clusters must be
performed in a virtual environment. A virtual environment can be
considered as a directory on the cluster where the user has write access
to. This directory contains configurations for the environment as well
as the packages themselves. There are several solutions for managing
virtual environments (also called environment managers) in Python such
as venv, pipenv and conda. venv and pipenv only
manage environments, but actual package installations must be done using
package managers such as pip or setuptools. On the other hand,
conda can not only manage environments, but also install packages
from the Anaconda repositories which host a large collection of binary
packages. Users can also install packages using pip inside a
conda environment. We found that most HPC centers recommend using
conda for managing Python virtual environments and we will use it
for the examples presented in this document as well.
To install a Python package, users first need to create a virtual
environment using conda or venv. This process is shown with the
green arrow in Figure 1. Users can specify a
name for the environment or provide a path to its location. Once an
environment is created, users must activate it so that the installed
packages are visible to the Python interpreter. Activating an
environment enables a user to install new packages inside the
environment or to run codes using the installed packages. Users can also
list the packages installed in an environment or export it to a
specification file (follow the orange arrow in Figure
1). In Anaconda, the specification file is
formatted as a YAML file and it can contain detailed names and versions
for all packages. Users can share the specification file with colleagues
or use it to recreate the environment at a later time.
Figure 1: Tasks related to managing Python packages in HPC environments. Each use-case in Table 2 is displayed with a different color in this diagram. Arrows with the same color show the steps that users need to execute for each task. Circles represent steps of each task and various conda subcommands are shown with a green circle. For example, to list all the packages in an environment (shown here with the yellow arrow), users must first activate the environment and then run the conda list command.
Most HPC centers also provide steps for using an environment in Jupyterhub. To install and use a custom package in Jupyterhub, users must install the ipykernel package in the environment along with other desired packages (follow the blue arrow in Figure 1). They must also create a kernel specification file in their Jupyter configuration directory. Some HPC centers provide custom tools for creating Jupyter kernels [9, 12]; we note this as an important step for alleviating some of the user burdens while managing Python packages.
In Table 3, we provide specific
conda commands for different steps highlighted in Figure
1. Similar analogies can be made for other
virtual environments such as pipenv or venv. Users are recommended to
consult the official conda documentations
[13] for detailed description of each
subcommand.
Task |
|
|---|---|
List all environments |
|
Create environment |
|
|
|
|
|
Activate environment |
|
|
|
Install packages |
|
|
|
Deactivate environment |
|
|
|
Install |
|
Create jupyter kernel |
|
List installed packages |
|
Export installed packages |
|
Recreate environment |
|
Delete environment |
|
|
Below we present a summary of the recommended environment managers and package managers across different HPC centers. Majority of the sites preferred conda and venv as environment managers. Although there are some common themes (e.g. how to run mpi4py, how to use Jupyter, etc.), the documentations have varying level of details. Due to the widely varying Python environments and their system dependencies, users can easily make mistakes as they move from one cluster to another.
HPC site |
Recommended environment manager |
Recommended package manager |
Other instructions |
|---|---|---|---|
OLCF [5] |
conda, venv |
pip, conda |
|
NERSC [4] |
conda |
pip, conda |
|
LLNL [8] |
virtualenv, conda |
pip |
|
Compute Canada [11] |
virtualenv |
pip |
|
CSCS [6] |
venv |
pip |
|
TACC [19] |
venv |
pip |
|
NCAR [20] |
conda, mamba |
conda, mamba |
|
Purdue RCAC [9] |
conda |
conda, pip |
|
Yale CRC [10] |
conda, mamba |
conda, pip |
|
2.2. Running MPI codes with Python
Several large HPC centers provide instructions for running MPI codes with Python [4, 5, 11]. In order to run parallel codes, users must load appropriate compiler and MPI libraries from the system before installing the Python packages (mpi4py, h5py etc.). They must also load the MPI libraries while running their codes. Installing both mpi4py and h5py with appropriate compiler and MPI combinations is fairly challenging considering the dependency on vendor-provided MPI libraries. Both [4] and [5] provide step-by-step commands for installing and testing mpi4py and h5py on their respective clusters. In addition, [4] provides a pre-installed mpi4py environment and recommends users to clone it—a much welcome simplification for the users.
Moreover, all the sites highlighted the negative impact of parallel Python codes on filesystems.
During startup, parallel Python codes can generate a lot of accesses to small files and can, therefore,
lead to IO bottlenecks. Multiple solutions with varying degrees of sophistication are provided to
alleviate such contentions: i) to create the Python environment inside a container, ii) to create
the Python environment locally on each node, or iii) to use the fastest parallel filesystem and to avoid
the home directory. Another important consideration for running parallel Python codes is not to oversubscribe the
cores. For example, a mpi4py code that occupies all the cores on a system can also load multi-threaded
libraries such as numpy, thereby, accidentally oversubscribing the physical cores. This can be avoided
by setting appropriate number of threads (OMP_NUM_THREADS) per MPI rank.
We note that configuring parallel Python applications is site-specific and users can benefit from simple scripts developed by HPC center staff to automate the installation and environment configuration process.
2.3. Troubleshooting guide
We found only a handful of HPC centers provide steps to troubleshoot
Python package installation issues. For example, at our center, users
commonly run out of storage space by allowing pip or conda to
cache packages over a long period. Similarly, installations in the
user’s site-packages directory ($HOME/.local) can interfere with
packages in the environments. It is beneficial to provide a step-by-step
troubleshooting guide for users or automate parts of the troubleshooting
process using a tool. We refer users to [9]
for some of the troubleshooting steps that they can follow.
3. Need for site-specific customization and automation
During our survey of Python documentations among HPC centers, we found
that there are many configurations that can be deployed at a site-wide
location. These configurations can be used to control the behaviors of
package managers such as pip and conda and can significantly
reduce the number of arguments that users need to provide via command
line. Site-wide configurations can also help ensure that users are
following the best practices deemed necessary by the center staff.
Advanced users can, of course, override these configurations with their
personal configurations or by specifying preferences in the command
line. We present some example configurations for pip and conda
that can be deployed site-wide.
3.1. Configuring pip with pip.conf
The behavior of the pip package manager can be controlled by
deploying a global configuration file in /etc/pip/pip.conf. Some
configurations that can be deployed site-wide are:
Location of cache directory: By default
pipsaves installation tarballs and temporary build files in a cache directory in the user’s home. This can be changed to the project directory ($PROJECT) to avoid home directory filling up.Enable build from source: Most documentations recommend that users should install packages from source by specifying
–no-binaryin the command line. This option can be specified inpip.confso that users don’t have to specify it every time.
3.2. Configuring conda with .condarc
Similar to pip, the behavior of conda can also be controlled by
using the configuration file .condarc. This can be deployed in
users’ home directories or by deploying it in the Anaconda installation
directory (warning: the system ``.condarc`` takes precedence over
users’ personal ``.condarc``). Users can benefit from setting these in
a file instead of having to specify at every command invocation.
Set cache dir: Similar to pip, we can also use the
$PROJECTdirectory forcondacaches to avoid filling the home directory.Set environment path: By default
condacreates environments in users’ home directories which are not suitable for package installations (limited space, IO bottlenecks, etc.). Sites can specify custom directories for creating environments, e.g.,$PROJECT/$USER/$PYTHON_VER.Set channels: Center staff can also specify which
condachannels are used by default for package installations (e.g. useconda-forgeinstead ofdefault). Users can override these by specifying channels explicitly.Use strict channel priority: Using strict channel priority can speed up dependency resolution and improve package installation experience.
3.3. Export environment variables
Many of the configurations specified in the previous two sections can also be specified by exporting appropriate environment variables in the Python module file. Example environment variables that can be exported in Python module files:
CONDA_ENVS_PATH: Specify where environments are created by default.CONDA_CACHE_DIR: Specify wherecondawill cache packages.PYTHONNOUSERSITE: Do not use user’s site-packages when using the environment.
3.4. Creating jupyter kernels
In earlier sections we highlighted that using a package in Jupyterhub
requires additional steps to configure and generate the Jupyter kernel.
This can be a daunting task for many scientists and can, therefore,
benefit from automation. For example, we can preinstall ipykernel and
generate a jupyter kernel as part of the procedure to create virtual
environments. This is the exact solution adopted in the
conda-env-mod tool deployed at Purdue
[18]. The jupyter kernel can be
further customized by using a site-specific template. For example,
additional environment variables may be initialized in the kernel
definition (set OMP_NUM_THREADS). Doing all these configurations
manually can be quite complex for an average user and may lead to
errors.
3.5. Provide flexible activation and deactivation via module files
One of the issues we have faced while using conda is its limitations
in activating and deactivating environments. i) Some sites prefer using
source activate or deactivate for activating (deactivating) an
environment, but it is only applicable for bash users. Users using other
shells (e.g. tcsh) cannot use this approach. ii) In some versions of
conda, using conda activate requires users to run conda init
beforehand. But conda init adds code blocks in users’ shell
initialization files which leads to other issues. iii) Using
conda deactivate can often unset environment variables set by other
environment modules, thereby, corrupting the user’s environment. iv)
Users are unable to activate multiple environments at the same time. For
example, a scientist can choose to create two environments–one with a
set of stable packages (numpy, matplotlib, seaborn, etc.)
and another with an experimental package which gets frequently updated.
If the environments have compatible python versions, they may be used
together in the user’s code. But conda cannot provide flexible
activation of both environments at the same time. We argue that Python
environments can be activated or deactivated much more easily through
the familiar interface of module files. The module files, in this case,
can define the PYTHONPATH variable pointing to the environment and
can also point to binary locations in the environment. Apart from these,
module files have the capability to capture additional dependency on
system compilers and libraries (e.g. MPI libraries) that were loaded
during the package installation and they can later be loaded automatically. The
conda-env-mod tool generates module files from Python environments
and provides users with instructions for loading the modules. We have
observed that it also makes it much easier to share Python environments
among members of a research group. One person in the group can assume the role of
the maintainer and other users only need to generate the module file
from the shared environment directory. More details about the motivation
for using module files and how conda-env-mod simplifies environment
management can be found in our HUST’20 paper
[3].
3.6. Overview of conda-env-mod
conda-env-mod is a tool for simplifying Python package installation
and usage on HPC clusters developed at Purdue University. Using
conda-env-mod, users can take a 3-step approach to install and use
Python packages (Figure 2) At first,
the user specifies a name or location for the Python environment.
conda-env-mod then internally uses Anaconda to create a new
environment and generates a module file for the environment. The user
then loads the module file to activate the environment. In the final
step, the user installs her desired packages using pip or conda
commands. It also has the ability to automatically configure an
environment to be used in Jupyter. Moreover, conda-env-mod can be
used as a standalone tool for creating a module file from a Python
environment or for creating a jupyter kernel. The current implementation
of conda-env-mod can support the use-cases 1-3,5,7-8 in Table
2. It is publicly available for
download on Github [18].
Figure 2: conda-env-mod helps users create and use Anaconda environments in 3 simple steps. It can also automatically create module files and Jupyter kernels from environments.
4. Additional requirements for conda-env-mod
During the early phases of this project, we solicited feedback from the
BSSw community about the current features of conda-env-mod and what
additional features were needed to make it useful to a larger number of
users. We received several detailed responses from the community
[21]. Based on these feedback,
we have identified that the following improvements to conda-env-mod
are necessary. Adding these features will also help us automate all the
use-cases identified in Table 2.
Improve installation and configuration procedures. Some users found it difficult to install and use
conda-env-modout-of-the-box. We will improve the installation and configuration procedure by guiding users through a questionnaire when they run it for the first time.Improve documentation. The current documentation of
conda-env-modis available as man pages. We will update the documentation with more examples and host it on readthedocs website so that users can easily find help.Create environments from environment specification files. One of the important use-cases identified in Table 1 is the ability to create an environment from an environment specification file, equivalent to the
conda create -fsubcommand. The need for this is also highlighted in the conversation in [21]. This capability will allow users to create environments from a YAML or text specification file.Export an environment to a specification file. This allows a user to save the current state of their environment into a specification file (use cases 6,9). Users can then share the environment with other colleagues or can recreate the environment from a previous state.
Enable TCL module files, bash and csh script generation.
conda-env-modcurrently generates modules files in Lmod format (lua scripts). We want to support more users by also generating TCL modules or by generating bash or csh scripts that can be easily sourced.Enable site-specific module file templates.
conda-env-modcurrently generates module file from a fixed template embedded in the code. However, sites may need to customize the module file to incorporate additional configurations (e.g. to control openmp threading in python,OMP_NUM_THREADSorMKL_NUM_THREADS). We want to enable such customization by making the module file generation code more flexible.Include additional modules as dependencies.
conda-env-modcurrently does not capture additional modules that are loaded at the time of environment creation. However, those may be essential for successfully running codes with the environment. For example, we may need to load the exact same compiler and MPI modules at runtime. We want to capture such dependencies in the generated module file.List existing environments and module files. Users may need to list what environments they have already created or which modules are available to activate those environments (use-case 4).
Create unit tests for various subcommands. We will create unit tests for various subcommands of
conda-env-mod. This is to ensure that the tool does not break as we add new features.Use Python from the environment by default (completed): By default
conda-env-modinstalls Python inside the new environment to keep it self-contained. It was recommended by users that we should use Python from the environment as opposed to using the Python from the base Anaconda. This change has already been implemented.Create sample
.condarcandpip.conffiles. As described in Section 3, default behaviors of package managers can be updated by site-wide configuration files. We will share sample configuration files that centers can easily adopt and update.
We anticipate the following timeline for implementing the features.
Weeks 1-2 |
Tasks 1-2 |
Weeks 3-4 |
Tasks 3-4 |
Weeks 5-6 |
Tasks 5-6 and 11 |
Weeks 7-8 |
Tasks 7-9 |
5. Conclusion
In this article, we have provided a summary of best practices for
managing Python packages from various HPC centers around the globe.
Based on the use-cases identified in these documents, we present a
diagram highlighting the tasks associated with Python package management
on HPC clusters. We also identify the steps that can benefit from
automation or site-specific customizations. Our proposed tool,
conda-env-mod implements these best practices and simplifies the
process of environment creation and use in a HPC cluster. After
conversation with community members, several new features have been
suggested for conda-env-mod which will be implemented in the coming
months.
6. References
Karolina Jaworek. Why Python is growing so quickly - future trends. June 2018. URL: https://www.netguru.com/blog/future-trends-in-python.
Wolfgang Resch. Python in hpc. 2023. URL: https://hpc.nih.gov/training/handouts/171121_python_in_hpc.pdf.
Amiya K. Maji, Lev Gorenstein, and Geoffrey Lentner. Demystifying python package installation with conda-env-mod. In 2020 IEEE/ACM International Workshop on HPC User Support Tools (HUST) and Workshop on Programming and Performance Visualization Tools (ProTools), volume, 27–37. 2020. doi:10.1109/HUSTProtools51951.2020.00011.
Nersc - brief introduction to python at nersc. 2023. URL: https://docs.nersc.gov/development/languages/python/.
Olcf - python on olcf systems. 2023. URL: https://docs.olcf.ornl.gov/software/python/index.html.
Olcf - jupyter user guide. 2023. URL: https://docs.olcf.ornl.gov/services_and_applications/jupyter/index.html.
Llnl - python documentation. 2023. URL: https://hpc.llnl.gov/software/development-environment-software/python.
Purdue rcac - python user guide. 2023. URL: https://www.rcac.purdue.edu/knowledge/negishi/run/examples/apps/python.
Conda at Yale Center for Research Computing. 2020. URL: https://docs.ycrc.yale.edu/clusters-at-yale/guides/conda/.
Compute canada - python documentation. 2023. URL: https://docs.alliancecan.ca/wiki/Python.
Cscs - jupyterlab documentation. 2023. URL: https://user.cscs.ch/tools/interactive/jupyterlab/.
Conda user guide. 2023. URL: https://docs.conda.io/projects/conda/en/stable/user-guide/index.html.
Conda configuration guide. 2023. URL: https://conda.io/projects/conda/en/latest/user-guide/configuration/use-condarc.html.
Pip user guide. 2023. URL: https://pip.pypa.io/en/stable/user_guide/.
Pip configuration guide. 2023. URL: https://pip.pypa.io/en/stable/topics/configuration/.
Pipenv user guide. 2023. URL: https://pipenv.pypa.io/en/latest/install/.
Amiya Maji and Lev Gorenstein. Conda-env-mod: a tool for simplifying Python package installation in HPC clusters. 2019. URL: https://github.com/amaji/conda-env-mod.
Todd Evans, Antonio Gómez-Iglesias, and Cyrus Proctor. PyTACC: HPC Python at the Texas Advanced Computing Center. In Proceedings of the 5th Workshop on Python for High-Performance and Scientific Computing, PyHPC '15, 4:1–4:7. New York, NY, USA, 2015. ACM. URL: http://doi.acm.org/10.1145/2835857.2835861, doi:10.1145/2835857.2835861.
Ncar - using conda and python. 2023. URL: https://arc.ucar.edu/knowledge_base/83853599.
Amiya Maji. Community discussion - simplifying Python package installation in HPC clusters. 2022. URL: https://github.com/amaji/conda-env-mod/issues/2.
Zahra Ronaghi, Rollin Thomas, Jack Deslippe, Stephen Bailey, Doga Gursoy, Theodore Kisner, Reijo Keskitalo, and Julian Borrill. Python in the NERSC exascale science applications program for data. In Proceedings of the 7th Workshop on Python for High-Performance and Scientific Computing, PyHPC'17, 4:1–4:10. New York, NY, USA, 2017. ACM. URL: http://doi.acm.org/10.1145/3149869.3149873, doi:10.1145/3149869.3149873.
Daniel Gall and Frank Indiviglio. Managing Python in HPC environments. In Proceedings of the 8th Workshop on Python for High-Performance and Scientific Computing, PyHPC'18. 2018. URL: https://sc18.supercomputing.org/proceedings/workshops/workshop_files/ws_phpsc103s3.pdf.
M. Geimer, K. Hoste, and R. McLay. Modern scientific software management using EasyBuild and Lmod. In 2014 First International Workshop on HPC User Support Tools, volume, 41–51. 2014.
Rollin Thomas, William Scullin, and Matt Belhorn. Python in HPC. 2017. URL: https://www.exascaleproject.org/wp-content/uploads/2017/05/IDEAS-Python-in-HPC-Thomas-Scullin-Belhorn.pdf.
Mamba user guide. 2023. URL: https://mamba.readthedocs.io/en/latest/.
Venv - creation of virtual environments. 2023. URL: https://docs.python.org/3/library/venv.html.
John Walk. Managing python environments. 2020. URL: https://www.pluralsight.com/tech-blog/managing-python-environments/.