5

I need to write a script to start gunicorn + django site which developed with pyenv the script is something like

#!/bin/bash
                                                                                
pyenv activate .ve
pyenv exec gunicorn config.wsgi:application --name mini2 --workers 8 \
--workers 8 --bind=unix:/tmp/run/mini2.socket \
--log-level=debug --log-file=-

and the error message

2021-12-06 14:09:00 [mini2@s017 mini2]$ ./prodution.sh 

Failed to activate virtualenv.

Perhaps pyenv-virtualenv has not been loaded into your shell properly.
Please restart current shell and try again.

2021-12-06 14:09:55 [mini2@s017 mini2]$ 

I can run the script line by line. so there must be something wrong in the script , but I have no clue what's going wrong.

I had already append couple lines about pyenv in my bashrc

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
if command -v pyenv 1>/dev/null 2>&1; then
 eval "$(pyenv init -)"
fi

so is there anyway to activate virtualenv create by pyenv in bash script ? any suggestions ??

update:

according to Failed to activate virtualenv with pyenv

I update my .bashrc

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
#if command -v pyenv 1>/dev/null 2>&1; then
# eval "$(pyenv init -)"
#fi

but still not working.

my test script
#!/bin/bash

pyenv activate .ve

and the error 

Failed to activate virtualenv.

Perhaps pyenv-virtualenv has not been loaded into your shell properly.
Please restart current shell and try again.
Eric Chang
  • 51
  • 1
  • 3
  • Try [python - Failed to activate virtualenv with pyenv - Stack Overflow](https://stackoverflow.com/questions/45577194/failed-to-activate-virtualenv-with-pyenv) (see also [python - Using 'pyenv activate' in a Dockerfile - Stack Overflow](https://stackoverflow.com/questions/40330039/using-pyenv-activate-in-a-dockerfile)) . You didn't have all of the commands. – user202729 Dec 06 '21 at 07:15
  • `activate` should only be relevant for interactive shells. Your `pyenv exec` should work without the `activate`. ~/.bashrc is also only used by interactive shells. – jordanm Dec 06 '21 at 08:31
  • @jordanm so , what's your suggestion ? how to update the script ? – Eric Chang Dec 06 '21 at 08:38
  • Interesting, I seem to have the same problem but I never noticed because I activate my environment by sourcing activate directly ```source .ve/bin/activate``` – RSale Dec 30 '21 at 20:57

2 Answers2

4

Instead of using

${PYENV_ROOT}/versions/<venv name>/bin/python script.py

as suggested in other answers, you could activate the environment "manually":

. ${PYENV_ROOT}/versions/<venv name>/bin/activate
python script.py

Note that the dot before ${PYENV_ROOT} is equal to the source command.

This has the benefit of leaving python script.py as the command line instead of /home/<user>/<pyenv root>/versions/<venv name>/bin/python script.py, which could be helpful in htop for example.

This would mean that replacing

pyenv activate .ve

with

. ${PYENV_ROOT}/versions/.ve/bin/activate

would fix your issue, provided that .ve is the name of the virtual environment.

robertspierre
  • 3,218
  • 2
  • 31
  • 46
Daniel F
  • 13,684
  • 11
  • 87
  • 116
2

There is no need to pyenv activate the virtual environment in your script. Because of how virtual environments work [1], you need only use the absolute path to the Python interpreter binary. You can confirm this path using $ pyenv which python whilst your environment is activated. The most substantive thing that pyenv activate does is prepend the interpreter binary to your PATH such that python, python3, etc. will resolve to it [2]. The pyenv initialization commands in your .bashrc only serve to enable shell auto-completion, rehash shims, and define a pyenv shell function [3].

TLDR:

#!/bin/bash

"${PYENV_ROOT}/versions/<venv name>/bin/python" script.py
  • Thanks for this useful answer, but the double quotes convert the command into a string. – Daniel F Nov 02 '22 at 13:14
  • 1
    @DanielF I'm not certain in what context you are referring to, but I clarified the example above to make it clear that it is BASH. If you omitted the quotes and the expanded path had spaces, it would not be interpreted correctly by the shell. – scienceplease Nov 02 '22 at 18:48
  • My apologies, my mistake. I tried it once with quotes and it didn't work so I removed them, I can't remember exactly what I was executing, but my command should run inside gnu-screen like `screen -AmdS test "${PYENV_ROOT}/versions/test-env/bin/python" test.py` and I got an error. But I tried it again now and it works. I think I was in the wrong working directory or something. Thanks for making me check again. – Daniel F Nov 02 '22 at 20:37