How to activate a conda environment in a remote machine(Solution + analysis)

I have encountered this problem while trying to activate my virtual environment in a remote machine using SSH. The environment on both sides is Linux. My PC is actually on Windows 10. Thanks to a new Ubuntu container available in Window10, it is highly convenient to run Ubuntu without launching a virtual machine.

Want to know how to resolve Your shell has not been properly configured to use ‘conda activate‘ error? Here is an efficient and clear solution!

Problem:

>>> conda activate 

While executing the command above, I got the following error:

CommandNotFoundError: Your shell has not been properly configured to use 'conda activate'.
To initialize your shell, run

    $ conda init 

Currently supported shells are:
  - bash
  - fish
  - tcsh
  - xonsh
  - zsh
  - powershell

See 'conda init --help' for more information and options.

IMPORTANT: You may need to close and restart your shell after running 'conda init'.

Verification:

Of course, I follow the instruction and run the conda init command. No luck. Then I verify the status of the conda environment:

>>> which conda
==> /home/zkang/.condarc <==
ssl_verify: True
channels:
  - defaults
>>> conda info
     active environment : None
       user config file : /home/zkang/.condarc
 populated config files : /home/zkang/.condarc
          conda version : 4.7.12
    conda-build version : 3.18.9
         python version : 3.7.4.final.0
       virtual packages : __cuda=10.2
       base environment : /anaconda3  (writable)
           channel URLs : https://repo.anaconda.com/pkgs/main/linux-64
                          https://repo.anaconda.com/pkgs/main/noarch
                          https://repo.anaconda.com/pkgs/r/linux-64
                          https://repo.anaconda.com/pkgs/r/noarch
          package cache : /anaconda3/pkgs
                          /home/zkang/.conda/pkgs
       envs directories : /anaconda3/envs
                          /home/zkang/.conda/envs
               platform : linux-64
             user-agent : conda/4.7.12 requests/2.22.0 CPython/3.7.4 Linux/4.15.0-76-generic ubuntu/18.04.4 glibc/2.27

So we are sure that conda is installed in the remote machine. Then how to activate my environment?

Solution:

A simpler and cleaner solution is as follows. You

>>> eval "$(conda shell.bash hook)"
>>> conda activate 

Then the environment can be activated correctly.

Why?

I found this solution in various answers, but they hardly explain why we should do this. Well, I have to say that I am not an expert to the command line nor the conda configuration. I can only dig a little bit deeper and try to reveal some of the truth.

The magic of the command eval can be found here. The basic idea is that the eval command first evaluates the argument and then runs the command stored in the argument. In this case, it means that the script generated by conda shell.bash hook is executed. So what is this script?

Let's have a look:

>>> conda shell.bash hook
export CONDA_EXE='/anaconda3/bin/conda'
export _CE_M=''
export _CE_CONDA=''
export CONDA_PYTHON_EXE='/anaconda3/bin/python'

# Copyright (C) 2012 Anaconda, Inc
# SPDX-License-Identifier: BSD-3-Clause

__add_sys_prefix_to_path() {
    # In dev-mode CONDA_EXE is python.exe and on Windows
    # it is in a different relative location to condabin.
    if [ -n "${_CE_CONDA}" ] && [ -n "${WINDIR+x}" ]; then
        SYSP=$(\dirname "${CONDA_EXE}")
    else
        SYSP=$(\dirname "${CONDA_EXE}")
        SYSP=$(\dirname "${SYSP}")
    fi

    if [ -n "${WINDIR+x}" ]; then
        PATH="${SYSP}/bin:${PATH}"
        PATH="${SYSP}/Scripts:${PATH}"
        PATH="${SYSP}/Library/bin:${PATH}"
        PATH="${SYSP}/Library/usr/bin:${PATH}"
        PATH="${SYSP}/Library/mingw-w64/bin:${PATH}"
        PATH="${SYSP}:${PATH}"
    else
        PATH="${SYSP}/bin:${PATH}"
    fi
    \export PATH
}

__conda_hashr() {
    if [ -n "${ZSH_VERSION:+x}" ]; then
        \rehash
    elif [ -n "${POSH_VERSION:+x}" ]; then
        :  # pass
    else
        \hash -r
    fi
}

__conda_activate() {
    if [ -n "${CONDA_PS1_BACKUP:+x}" ]; then
        # Handle transition from shell activated with conda <= 4.3 to a subsequent activation
        # after conda updated to >= 4.4. See issue #6173.
        PS1="$CONDA_PS1_BACKUP"
        \unset CONDA_PS1_BACKUP
    fi

    \local cmd="$1"
    shift
    \local ask_conda
    OLDPATH="${PATH}"
    __add_sys_prefix_to_path
    ask_conda="$(PS1="$PS1" "$CONDA_EXE" $_CE_M $_CE_CONDA shell.posix "$cmd" "$@")" || \return $?
    PATH="${OLDPATH}"
    \eval "$ask_conda"
    __conda_hashr
}

__conda_reactivate() {
    \local ask_conda
    OLDPATH="${PATH}"
    __add_sys_prefix_to_path
    ask_conda="$(PS1="$PS1" "$CONDA_EXE" $_CE_M $_CE_CONDA shell.posix reactivate)" || \return $?
    PATH="${OLDPATH}"
    \eval "$ask_conda"
    __conda_hashr
}

conda() {
    if [ "$#" -lt 1 ]; then
        "$CONDA_EXE" $_CE_M $_CE_CONDA
    else
        \local cmd="$1"
        shift
        case "$cmd" in
            activate|deactivate)
                __conda_activate "$cmd" "$@"
                ;;
            install|update|upgrade|remove|uninstall)
                OLDPATH="${PATH}"
                __add_sys_prefix_to_path
                "$CONDA_EXE" $_CE_M $_CE_CONDA "$cmd" "$@"
                \local t1=$?
                PATH="${OLDPATH}"
                if [ $t1 = 0 ]; then
                    __conda_reactivate
                else
                    return $t1
                fi
                ;;
            *)
                OLDPATH="${PATH}"
                __add_sys_prefix_to_path
                "$CONDA_EXE" $_CE_M $_CE_CONDA "$cmd" "$@"
                \local t1=$?
                PATH="${OLDPATH}"
                return $t1
                ;;
        esac
    fi
}

if [ -z "${CONDA_SHLVL+x}" ]; then
    \export CONDA_SHLVL=0
    # In dev-mode CONDA_EXE is python.exe and on Windows
    # it is in a different relative location to condabin.
    if [ -n "${_CE_CONDA+x}" ] && [ -n "${WINDIR+x}" ]; then
        PATH="$(\dirname "$CONDA_EXE")/condabin${PATH:+":${PATH}"}"
    else
        PATH="$(\dirname "$(\dirname "$CONDA_EXE")")/condabin${PATH:+":${PATH}"}"
    fi
    \export PATH

    # We're not allowing PS1 to be unbound. It must at least be set.
    # However, we're not exporting it, which can cause problems when starting a second shell
    # via a first shell (i.e. starting zsh from bash).
    if [ -z "${PS1+x}" ]; then
        PS1=
    fi
fi

If I understand correctly, this script explicitly define some behaviors of the command conda, e.g. activate|deactivate|install|update|upgrade|remove|uninstall. For instance, if we type the command conda activate <env_name>, it would call __conda_activate() function to initialize the environment.

In this way, we don't need to go through the annoying conda init command. As a result, the initialization can be done and the script automatically activates the base environment for use.

That's it! Since I have now the environement ready, I can run my tasks on the remote server freely.

Reference

https://askubuntu.com/questions/849470/how-do-i-activate-a-conda-environment-in-my-bashrc

https://github.com/conda/conda/issues/7980

https://stackoverflow.com/questions/34534513/calling-conda-source-activate-from-bash-script

Leave a Reply

Your email address will not be published. Required fields are marked *