Try

Or browse

    macOSPythonAnsible ‍Code

    Conda for Python environment management on macOS

    Conda for Python environment management on macOS

    Learn how to efficiently manage Python environments on your MacBook Pro using Conda. This comprehensive guide covers installation, creating and activating environments, installing packages, and best practices for streamlining your Python development workflow.

    Suggest editsRSSFollow on Google

    As mentioned in a previous post, I recently finished writing the second edition of Learn Ansible. This had me using Python a lot, and my one key takeaway is that managing Python has become a massive chore. Now, with the book complete, I thought I would strip back on my machine, start from scratch - or as close to clean as I could get - and develop a cleaner, more streamlined way of managing Python on my local machine.

    I have tried a few methods in the past-see these posts from December 2019, January 2021 and October 2021. While these worked, they quickly became a chore to maintain due to all the different things that were trying to use Python. For example, there is the version of Python built into macOS, Homebrew tries to maintain its own Python installations for packages it downloads, and then there is my stuff on top.

    Introducing Conda

    I did a little research and chose Conda - which can be found here↗. While we will cover the Conda command in this post - I am using Miniconda↗.

    Miniconda is described as the following:

    Miniconda is a free minimal installer for conda. It is a small bootstrap version of Anaconda that includes only conda, Python, the packages they both depend on, and a small number of other useful packages (like pip, zlib, and a few others).

    So, as I wanted to keep things as simple as possible, I used Miniconda rather than the more full-fat Anaconda.

    Installing and configuring Miniconda on macOS

    The installation guide for Miniconda is simple if you are using Homebrew↗, you just need to run the following command:

    Installing Miniconda
    brew install miniconda

    Once installed, we must ensure it is loaded when we open our terminal. To add the right lines to ~/.zshrc run the following command:

    Update the ~/.zshrc file
    conda init zsh

    This adds the following code to the end of ~/.zshrc:

    Contents appended to ~/.zshrc (TEXT)
    # >>> conda initialize >>>
    # !! Contents within this block are managed by 'conda init' !!
    __conda_setup="$('/opt/homebrew/Caskroom/miniconda/base/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
    if [ $? -eq 0 ]; then
    eval "$__conda_setup"
    else
    if [ -f "/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh" ]; then
    . "/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh"
    else
    export PATH="/opt/homebrew/Caskroom/miniconda/base/bin:$PATH"
    fi
    fi
    unset __conda_setup
    # <<< conda initialize

    I have already updated my dotfiles to include the above and also to use the Powerline10k theme↗ so it shows the Conda environment that is currently selected in my terminal:

    As you can see from the prompt above, where it shows base on the right-hand side - with base being the default environment.

    Adding an Ansible environment

    In this example, I will create an environment for running Ansible; let’s start by creating the environment itself.

    Creating the environment

    To add an environment for running just Ansible, I ran the following command:

    Creating the Ansible environment
    conda create -n ansible python=3.12

    The command gave me the following output:

    Output of the create command
    Channels:
    - defaults
    Platform: osx-arm64
    Collecting package metadata (repodata.json): done
    Solving environment: done
    ## Package Plan ##
    environment location: /opt/homebrew/Caskroom/miniconda/base/envs/ansible
    added / updated specs:
    - python=3.12
    The following packages will be downloaded:
    package | build
    ---------------------------|-----------------
    bzip2-1.0.8 | h80987f9_5 129 KB
    ca-certificates-2024.3.11 | hca03da5_0 128 KB
    python-3.12.2 | h99e199e_0 14.0 MB
    tzdata-2024a | h04d1e81_0 116 KB
    xz-5.4.6 | h80987f9_0 372 KB
    ------------------------------------------------------------
    Total: 14.8 MB
    The following NEW packages will be INSTALLED:
    bzip2 pkgs/main/osx-arm64::bzip2-1.0.8-h80987f9_5
    ca-certificates pkgs/main/osx-arm64::ca-certificates-2024.3.11-hca03da5_0
    expat pkgs/main/osx-arm64::expat-2.5.0-h313beb8_0
    libcxx pkgs/main/osx-arm64::libcxx-14.0.6-h848a8c0_0
    libffi pkgs/main/osx-arm64::libffi-3.4.4-hca03da5_0
    ncurses pkgs/main/osx-arm64::ncurses-6.4-h313beb8_0
    openssl pkgs/main/osx-arm64::openssl-3.0.13-h1a28f6b_0
    pip pkgs/main/osx-arm64::pip-23.3.1-py312hca03da5_0
    python pkgs/main/osx-arm64::python-3.12.2-h99e199e_0
    readline pkgs/main/osx-arm64::readline-8.2-h1a28f6b_0
    setuptools pkgs/main/osx-arm64::setuptools-68.2.2-py312hca03da5_0
    sqlite pkgs/main/osx-arm64::sqlite-3.41.2-h80987f9_0
    tk pkgs/main/osx-arm64::tk-8.6.12-hb8d0fd4_0
    tzdata pkgs/main/noarch::tzdata-2024a-h04d1e81_0
    wheel pkgs/main/osx-arm64::wheel-0.41.2-py312hca03da5_0
    xz pkgs/main/osx-arm64::xz-5.4.6-h80987f9_0
    zlib pkgs/main/osx-arm64::zlib-1.2.13-h5a0b063_0
    Proceed ([y]/n)? y
    Downloading and Extracting Packages:
    Preparing transaction: done
    Verifying transaction: done
    Executing transaction: done
    #
    # To activate this environment, use
    #
    # $ conda activate ansible
    #
    # To deactivate an active environment, use
    #
    # $ conda deactivate

    Activating the environment

    With the dedicated Ansible environment created, we can activate using the following command:

    Activating the Ansible environment
    conda activate ansible

    We can now check the path of the python binary by running which python:

    Checking which python is being used
    which python
    /opt/homebrew/Caskroom/miniconda/base/envs/ansible/bin/python

    As you can see, it is using the python binary within our environment, which means that Ansible can now be installed along with some collections:

    Installing Ansible and some collections
    python -m pip install ansible
    ansible-galaxy collection install azure.azcollection
    python -m pip install -r ~/.ansible/collections/ansible_collections/azure/azcollection/requirements-azure.txt

    The screen below shows an example of what the terminal looks like when switched to the Ansible environment:

    So far so good !!!

    Digging Deeper

    Here are some notes on package management and virtual environment management.

    Pip vs Conda

    As well as being a Python environment manager, Conda also provides it own package management, so rather that running pip using

    Installing Ansible using pip
    python -m pip install ansible

    I could have run the following command:

    The Conda install command
    conda install conda-forge::ansible

    This would install Ansible from the main Anaconda↗ site, which hosts its own files at conda-forge/ansible↗ for Ansible, if I had taken this route the installation would have looked like the following:

    Going through the installation
    Channels:
    - defaults
    - conda-forge
    Platform: osx-arm64
    Collecting package metadata (repodata.json): done
    Solving environment: done
    ## Package Plan ##
    environment location: /opt/homebrew/Caskroom/miniconda/base/envs/ansible
    added / updated specs:
    - conda-forge::ansible
    The following packages will be downloaded:
    package | build
    ---------------------------|-----------------
    ansible-9.4.0 | pyh707e725_0 20.7 MB conda-forge
    ansible-core-2.16.5 | pyh707e725_0 1.3 MB conda-forge
    cryptography-42.0.5 | py312hd4332d6_0 1.4 MB
    jinja2-3.1.3 | py312hca03da5_0 327 KB
    markupsafe-2.1.3 | py312h80987f9_0 24 KB
    packaging-23.2 | py312hca03da5_0 169 KB
    pyyaml-6.0.1 | py312h80987f9_0 172 KB
    resolvelib-0.8.1 | py312hca03da5_0 30 KB
    yaml-0.2.5 | h1a28f6b_0 71 KB
    ------------------------------------------------------------
    Total: 24.1 MB
    The following NEW packages will be INSTALLED:
    ansible conda-forge/noarch::ansible-9.4.0-pyh707e725_0
    ansible-core conda-forge/noarch::ansible-core-2.16.5-pyh707e725_0
    cffi pkgs/main/osx-arm64::cffi-1.16.0-py312h80987f9_0
    cryptography pkgs/main/osx-arm64::cryptography-42.0.5-py312hd4332d6_0
    jinja2 pkgs/main/osx-arm64::jinja2-3.1.3-py312hca03da5_0
    markupsafe pkgs/main/osx-arm64::markupsafe-2.1.3-py312h80987f9_0
    packaging pkgs/main/osx-arm64::packaging-23.2-py312hca03da5_0
    pycparser pkgs/main/noarch::pycparser-2.21-pyhd3eb1b0_0
    pyyaml pkgs/main/osx-arm64::pyyaml-6.0.1-py312h80987f9_0
    resolvelib pkgs/main/osx-arm64::resolvelib-0.8.1-py312hca03da5_0
    yaml pkgs/main/osx-arm64::yaml-0.2.5-h1a28f6b_0
    Proceed ([y]/n)? n
    CondaSystemExit: Exiting.

    However, in my case, as I wanted to keep things simple - I am sticking to what I know and will use pip.

    I did, however, add the following alias for pip in my dotfile↗ to call python -m pip each time I run the pip command:

    Installing Python 3.10 (TEXT)
    alias pip='python -m pip'

    This means that if I run pip install ansible , the command python -m pip install ansible would be run, so I can be sure that I am not calling the pip executable from some other random place.

    Installing a different Python version

    Now, not every piece of code supports the latest and greatest version of Python. Luckily, as you might have already guessed, we can define what version of Python to install when you create your virtual environment using Conda.

    Installing Python 3.10
    conda create -n test python=3.10

    As you can see, we are requesting that Python 3.10 be installed instead of Python 3.12, which is what our other virtual environments use.

    The output of installing Python 3.10
    Channels:
    - defaults
    Platform: osx-arm64
    Collecting package metadata (repodata.json): done
    Solving environment: done
    ## Package Plan ##
    environment location: /opt/homebrew/Caskroom/miniconda/base/envs/test
    added / updated specs:
    - python=3.10
    The following packages will be downloaded:
    package | build
    ---------------------------|-----------------
    pip-23.3.1 | py310hca03da5_0 2.7 MB
    python-3.10.14 | hb885b13_0 13.0 MB
    setuptools-68.2.2 | py310hca03da5_0 942 KB
    wheel-0.41.2 | py310hca03da5_0 107 KB
    ------------------------------------------------------------
    Total: 16.7 MB
    The following NEW packages will be INSTALLED:
    bzip2 pkgs/main/osx-arm64::bzip2-1.0.8-h80987f9_5
    ca-certificates pkgs/main/osx-arm64::ca-certificates-2024.3.11-hca03da5_0
    libffi pkgs/main/osx-arm64::libffi-3.4.4-hca03da5_0
    ncurses pkgs/main/osx-arm64::ncurses-6.4-h313beb8_0
    openssl pkgs/main/osx-arm64::openssl-3.0.13-h1a28f6b_0
    pip pkgs/main/osx-arm64::pip-23.3.1-py310hca03da5_0
    python pkgs/main/osx-arm64::python-3.10.14-hb885b13_0
    readline pkgs/main/osx-arm64::readline-8.2-h1a28f6b_0
    setuptools pkgs/main/osx-arm64::setuptools-68.2.2-py310hca03da5_0
    sqlite pkgs/main/osx-arm64::sqlite-3.41.2-h80987f9_0
    tk pkgs/main/osx-arm64::tk-8.6.12-hb8d0fd4_0
    tzdata pkgs/main/noarch::tzdata-2024a-h04d1e81_0
    wheel pkgs/main/osx-arm64::wheel-0.41.2-py310hca03da5_0
    xz pkgs/main/osx-arm64::xz-5.4.6-h80987f9_0
    zlib pkgs/main/osx-arm64::zlib-1.2.13-h5a0b063_0
    Proceed ([y]/n)? y
    Downloading and Extracting Packages:
    Preparing transaction: done
    Verifying transaction: done
    Executing transaction: done
    #
    # To activate this environment, use
    #
    # $ conda activate test
    #
    # To deactivate an active environment, use
    #
    # $ conda deactivate

    As you can see from the screen below, switching to the new virtual environment loads the older version:

    Managing Virtual Environments

    You can list all of your virtual environments using the command below:

    Listing all envs
    conda env list

    This will return something like the following:

    The output of conda env list
    # conda environments:
    #
    base * /opt/homebrew/Caskroom/miniconda/base
    ansible /opt/homebrew/Caskroom/miniconda/base/envs/ansible
    discogs /opt/homebrew/Caskroom/miniconda/base/envs/discogs
    test /opt/homebrew/Caskroom/miniconda/base/envs/test

    Now let’s remove the test virtual environment:

    Removing the test env
    conda remove -n test --all

    This will nuke everything to do with the test virtual environment:

    The output of conda remove -n test --all
    Remove all packages in environment /opt/homebrew/Caskroom/miniconda/base/envs/test:
    ## Package Plan ##
    environment location: /opt/homebrew/Caskroom/miniconda/base/envs/test
    The following packages will be REMOVED:
    bzip2-1.0.8-h80987f9_5
    ca-certificates-2024.3.11-hca03da5_0
    libffi-3.4.4-hca03da5_0
    ncurses-6.4-h313beb8_0
    openssl-3.0.13-h1a28f6b_0
    pip-23.3.1-py310hca03da5_0
    python-3.10.14-hb885b13_0
    readline-8.2-h1a28f6b_0
    setuptools-68.2.2-py310hca03da5_0
    sqlite-3.41.2-h80987f9_0
    tk-8.6.12-hb8d0fd4_0
    tzdata-2024a-h04d1e81_0
    wheel-0.41.2-py310hca03da5_0
    xz-5.4.6-h80987f9_0
    zlib-1.2.13-h5a0b063_0
    Proceed ([y]/n)? y
    Preparing transaction: done
    Verifying transaction: done
    Executing transaction: done
    Everything found within the environment (/opt/homebrew/Caskroom/miniconda/base/envs/test), including any conda environment configurations and any non-conda files, will be deleted. Do you wish to continue?
    (y/[n])? y

    Updating packages

    Even if, like me, you use pip there are still some packages managed by Conda in your Virtual environment, you can update them by switching to the virtual environment you want to update and then run:

    Updating the Conda managed packages in your env
    conda update --all

    Conclusion

    Managing Python environments can be a daunting task, especially when dealing with multiple projects and dependencies. However, by leveraging the power of Conda and Miniconda, you can streamline your Python environment management process and ensure a clean, efficient setup on your local machine.

    With Conda, you can easily create isolated Python environments for different projects, specifying the exact Python version and package requirements. This allows you to maintain separate environments for each project, avoiding conflicts and ensuring compatibility.

    By following the steps outlined in this post, you can install and configure Miniconda on your macOS system, create dedicated environments for tools like Ansible, and manage packages using either Conda’s package management or the familiar pip command.

    Additionally, Conda provides flexibility in installing different Python versions within each environment, enabling you to work with projects that require specific Python versions seamlessly.

    With the ability to list, remove, and update virtual environments and packages, Conda offers a comprehensive solution for Python environment management. By incorporating Conda into your workflow, you can enhance your productivity, maintain a clean development setup, and efficiently manage your Python projects.

    So, whether you’re a beginner or an experienced Python developer, embracing Conda for Python environment management can greatly simplify your development process and help you focus on writing awesome code!

    Share

    Related terms: AgentAI Coding AssistantAnsibleApplication Programming InterfaceClaude CodeCodex

    Comments