oste-popp
oste-popp

Reputation: 190

pip installs packages in virtualenv and globally when called from bash script

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.

Upvotes: 3

Views: 5460

Answers (1)

Nick H
Nick H

Reputation: 1079

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.

Upvotes: 5

Related Questions