3

I am trying to activate a python environment and installing some packages using pip in a bash file. It succeeds to install in the environment but also installs globally on my mac, and I don't understand why.

script.sh:

#!/bin/bash
source '<absolute path>/venv/bin/activate'
which pip
pip install psutil
pip list

output:

$ ./script.sh
<absolute path>/venv/bin/pip
...
Package          Version  
---------------- ---------
pip              19.0.3   
psutil           5.6.3    
setuptools       41.0.1  
wheel            0.33.1   

But, in another terminal without the virtual environment it also gets installed:

$ which pip
/usr/local/opt/python/libexec/bin/pip
$ pip list
Package          Version  
---------------- ---------
pip              19.0.3   
psutil           5.6.3   
setuptools       41.0.1    
wheel            0.33.1   

If i type the commands in the script one by one in the terminal, it works as expected.
What am i missing?

edit:
If i run pip freeze | xargs pip uninstall -y (either in env or globally) it removes the packages both in the virtualenv and globally.
If i run the script again and I list the content in 'site-packages' ls venv/lib/python3.7/site-packages the installed package is not there, so my 'venv/bin/pip' is somehow pointing to my global 'site-packages'?

edit2: I found a way to reproduce the behaviors.
1. create an environment python -m venv venv_test
2. activate the environment . venv_test/bin/activate
3. edit source '<absolute path>/venv_test/bin/activate' in script.sh
4. run script ./script.sh

Why does this make pip install globally?

If i skip 2. it works as expected.

oste-popp
  • 190
  • 1
  • 10

1 Answers1

5

Running this in a bash script runs the commands in a different shell, then returns you to your original shell. Running source <path>/bin/activate runs this in you current shell, hence this works from the command line. Your bash script looks like:

#!/bin/bash
source "<absolute path>/venv/bin/activate"
which pip
pip install psutil
pip listenter code here

If you call this with source script.sh this will run this in you current shell and should work as expected. Hope this helps. There is some other methods here: https://stackoverflow.com/a/13122219/7473057

An example method for virtualenvs:

  1. create an environment python -m venv venv_test or virtualenv venv_test
  2. activate the environment: source ./venv_test/bin/activate (on cmd line)
  3. run script ./script.sh, which has source "<absolute path>/venv/bin/activate" removed.

Alternatively, I think what you are after is a subshell, running everything inside, which is in the link above.

Nick H
  • 1,081
  • 8
  • 13
  • It should still install the packages in the virtual environment without `source`? I do not need the the environment after i have executed the script. – oste-popp Jun 18 '19 at 09:17
  • Maybe something like this then? https://stackoverflow.com/a/50829922/7473057 You could execute the `source "/venv/bin/activate"` in a subshell? – Nick H Jun 18 '19 at 09:23
  • I updated the question with an edit2. Do you have any idea? – oste-popp Jun 18 '19 at 09:30
  • 1
    You are activating it twice, not sure why you need to. This is a working method: 1. create an environment python -m venv venv_test 2. activate the environment: source ./venv_test/bin/activate (on cmd line) 3. run script ./script.sh, which has `source "/venv/bin/activate"` removed. – Nick H Jun 18 '19 at 09:34
  • Testing this on my system, my system python `/usr/bin/python` cannot see any packages I install in that environment – Nick H Jun 18 '19 at 09:38
  • Yes, i did not mean initially to do that, but when I do the pip installs globally. Your answer is good, but it does not help me. I want the the activation of the environment to happen in the "script.sh" shell, not my own. – oste-popp Jun 18 '19 at 09:40
  • Can you add your comment about the steps to your answer? – oste-popp Jun 18 '19 at 09:41