120

I'm trying to activate my conda env via a bash script. Even though the script runs fine and my PATH appears to be changed within the script, it's getting reset somehow after the script terminates. I can call source activate test from the cmd line and it works fine. An example along with output below.

script:

PycharmProjects/test » cat ./example.sh
echo "before calling source: $PATH"
source activate test
echo "after calling source: $PATH"

output:

./example.sh
before calling source: /Use rs/me/miniconda3/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/TeX/texbin

discarding /Users/me/miniconda3/bin from PATH
prepending /Users/me/miniconda3/envs/test/bin to PATH

after calling source: /Users/me/miniconda3/envs/test/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/TeX/texbin`

but if I echo $PATH after the script finishes, you can see that the $PATH has not changed (i.e. no /Users/me/miniconda3/envs/test/bin):

PycharmProjects/test » echo $PATH /Users/me/miniconda3/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/TeX/texbin

6
  • 1
    echo $PATH where says that? Are you running example.sh as a script itself (i.e. ./example.sh)? Instead of sourceing it (i.e. source example.sh)? Commented Dec 30, 2015 at 18:27
  • running example.sh as as script (./example.sh). I called echo $PATH after script finished running, just to show $PATH is not actually changed. Commented Dec 30, 2015 at 18:30
  • 2
    Running it as a script the changes stop with the shell running the script. That's why you need to source the activate script to make it apply to the running script/shell in the first place. Commented Dec 30, 2015 at 18:32
  • Possible duplicate of How to source virtualenv activate in a Bash script Commented Dec 30, 2015 at 18:36
  • I had the same problem and ended up forcing my script to be sourced. That caused other troubles (such as running it with set -e) - eventually it was worth changing to to "ordinary" run (not sourced) and apply the accepted answer. Thanks for asking this! Commented Dec 13, 2020 at 11:32

5 Answers 5

209

On more recent versions of conda (4.6+), I have noticed that the following works:

eval "$(conda shell.bash hook)"
conda activate <env-name>
Sign up to request clarification or add additional context in comments.

11 Comments

Could you please explain a little bit why do we need eval "$(conda shell.bash hook)"?
conda shell.bash hook returns a string of bash. I suppose you could right this out to a file and then source that file, but it is easier/faster to eval it.
@AnthonyScopatz That explains what you're doing, but not why. conda activate <env> works just fine without that eval expression, so it's still not clear why you're doing that.
When conda activate errors out requesting conda init to be run, the eval expression here makes it work without conda init.
Getting: CommandNotFoundError: Your shell has not been properly configured to use 'conda activate'.
|
51

Interactive Shell

The conda activate command is intended for interactive shell sessions. One solution is to deliberately run the script in an interactive shell. This can be done through a shebang (if planning to use ./example.sh call):

example.sh

#!/usr/bin/env bash -l
echo "before calling source: $PATH"
## `source activate` is deprecated
conda activate test
echo "after calling source: $PATH"

or, by specifying via flags to the shell:

## bash
bash -l example.sh

## zsh
zsh -i example.sh

All of these assume that the executing user has run conda init for the shell.

Using conda run

For programmatic execution within an environment, Conda provides the conda run command. Rather than muck around with shell state, let Conda guarantee execution within the environment:

crun_example.sh

echo "PATH outside environment: $PATH"

## printing shell variables is complicated by escaping
conda run -n test --live-stream bash -c "echo \"PATH inside environment: \${PATH}\""

## but realistic application is usually a non-trivial script
conda run -n test --live-stream python my_script.py

The --live-stream flag ensures that output (stdout and stderr) are streamed live. That flag is alternatively also named --no-capture-output (they are the exact same option).

By including that flag, conda will stream your command's output live. Otherwise, it buffers all of the output until the conda run command ends, and then outputs everything at once, which is usually undesired (for example, a pip install command could easily run for 15 minutes, and wouldn't show any output at all until it's finished, making the user believe that something is wrong or frozen unless you enable live-streaming).

See conda run --help for details, or read the online documentation.

3 Comments

conda run -n <env_name> --live-stream works for me
Thank you, this solution makes a lot more sense than all the "source/hack/import/eval" nonsense. The whole point of conda activate is to hook an INTERACTIVE USER SHELL to make all subsequent commands run inside the conda environment. It does a lot of stupid stuff with changing the prompt and PATH etc. But conda run is what we're instead supposed to be using for non-interactive shells, and is documented here. It is the correct way for SCRIPTS to run stuff inside the conda environment: docs.conda.io/projects/conda/en/latest/commands/run.html
works on Ubuntu 20.02
50

I have found the following to work on Mac OSX running a bash shell:

#!/bin/bash
source /Users/yourname/anaconda/bin/activate your_env
python --version # example way to see that your virtual env loaded as expected

Make sure you make the scripted executable with:

chmod +x yourscript.bash

2 Comments

It worked for me on ubuntu 18, conda 4.9. It took less time than the Anthony Scopatz approach. The reason is out of my understandings.
This is the right way to do. Use source.
7

See the link below,

digitalocean-how-to-read-and-set-environmental-and-shell-variables-on-a-linux-vps

below is the snippet from the website,

This is because environmental variables are only passed to child processes. There isn't a built-in way of setting environmental variables of the parent shell. This is good in most cases and prevents programs from affecting the operating environment from which they were called.

Comments

0

I am using a workstation with the spec:

  • Fedora 37
  • Bash: GNU bash, version 5.2.15(1)-release (x86_64-redhat-linux-gnu)
  • conda: 23.7.2

None of these solutions worked for me, neither using bash interactive mode, nor login mode, nor eval "$(conda shell.bash hook)", etc.

I have a workaround for this issue for everyone like me being unable to make those solutions worked:

  1. Create a bash file named activate.sh in the project folder with this content:
#!/bin/bash
conda activate your_env_name
  1. Add an alias in ~/.bash_aliases like this:
alias conda-activate='test -f $PWD/activate.sh && source $PWD/activate.sh'
  1. Run conda-activate in your project folder

I know the question is about macos, but this is the most referenced issue for this problem in stackoverflow and I think is a good place to post my solution here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.