Cómo obtener la activación de virtualenv en un script Bash

100

¿Cómo se crea un script Bash para activar un virtualenv de Python?

Tengo una estructura de directorio como:

.env
    bin
        activate
        ...other virtualenv files...
src
    shell.sh
    ...my code...

Puedo activar mi virtualenv por:

user@localhost:src$ . ../.env/bin/activate
(.env)user@localhost:src$

Sin embargo, hacer lo mismo desde un script Bash no hace nada:

user@localhost:src$ cat shell.sh
#!/bin/bash
. ../.env/bin/activate
user@localhost:src$ ./shell.sh
user@localhost:src$ 

¿Qué estoy haciendo mal?

Cerin
fuente
6
Cuando ejecuta un script de shell, en realidad está creando un nuevo shell. El objetivo de usar sourcees cambiar algo en el shell actual. Puede usar el python de virtualenv usando la ruta completa ./env/bin/python.
Pablo Navarro
@NgureNyaga, No, esa pregunta no es la misma que la mía. Están preguntando cómo abastecerse desde una ubicación arbitraria. Ya sé cómo hacer esto. Estoy preguntando cómo obtener una fuente dentro de un script bash personalizado y mantener la fuente.
Cerin

Respuestas:

80

Cuando obtiene, está cargando el script de activación en su shell activo.

Cuando lo hace en un script, lo carga en ese shell que se cierra cuando finaliza el script y vuelve a su shell original inactivo.

Tu mejor opción sería hacerlo en función

activate () {
  . ../.env/bin/activate
}

o un alias

alias activate=". ../.env/bin/activate"

Espero que esto ayude.

richo
fuente
para windows c: \ tutorial>. \ env \ Scripts \ active
max4ever
7
No tenía ni idea de lo que estaba sucediendo cuando hice el código fuente. Esto ha cambiado enormemente mis scripts de bash para mejor. ¡Gracias!
Robert Townley
1
Tu idea de alias funcionó muy bien para mí también. Solo una nota: tuve que ponerlo (alias abcdef = "fuente ... / bin / activar") en mi script .zshrc (o .bashrc para los usuarios de bash) para que funcione.
Shahins
Esta es una buena solución si tiene sus virtualenvs usando el nombre de carpeta predeterminado. Solía ​​tener más de un repositorio en la carpeta, haciendo un desastre en los virtualenvs. Cambié a este predeterminado ahora.
3manuek
3
Soy bastante nuevo en bash, etc. ¿Puedes expandir este ejemplo para que muestre el script completo?
AljoSt
57

Debería llamar al script bash usando source.

Aquí hay un ejemplo:

#!/bin/bash
# Let's call this script venv.sh
source "<absolute_path_recommended_here>/.env/bin/activate"

En tu caparazón simplemente llámalo así:

> source venv.sh

O como sugirió @outmind: (Tenga en cuenta que esto no funciona con zsh)

> . venv.sh

Ahí lo tienes, la indicación de la cáscara se colocará en tu mensaje.

Flavio García
fuente
2
o incluso simplemente ". venv.sh"
outmind
no importa lo que intente, esto source "/home/surest/Desktop/testservers/TEST_VENV/venv3/bin/activate"produce:/home/surest/Desktop/testservers/TEST_VENV/py3.sh: 10: /home/surest/Desktop/testservers/TEST_VENV/py3.sh: source: not found
Tampoco obtengo nada cuando escribo which sourceen un indicador de shell, sin embargo, source venv3/bin/activatehace lo que espero y abro el venv. ...
¿Por qué funciona esto, pero source ./env/bin/activate(con el mismo #!/bin/bashprefijo) no? ¿Cuál es la diferencia entre usar comillas y no usarlas?
blacksite
No tengo problemas para usar la fuente dentro del script sin comillas. Veo un problema source ./env/bin/activateporque esto es relativo a la ruta que está ejecutando, ¿verdad? Si cambia el directorio dentro del script, puede volverse relativo.
Flavio García
13

Aunque no agrega el prefijo "(.env)" al indicador de shell, encontré que este script funciona como se esperaba.

#!/bin/bash
script_dir=`dirname $0`
cd $script_dir
/bin/bash -c ". ../.env/bin/activate; exec /bin/bash -i"

p.ej

user@localhost:~/src$ which pip
/usr/local/bin/pip
user@localhost:~/src$ which python
/usr/bin/python
user@localhost:~/src$ ./shell
user@localhost:~/src$ which pip
~/.env/bin/pip
user@localhost:~/src$ which python
~/.env/bin/python
user@localhost:~/src$ exit
exit
Cerin
fuente
5
técnicamente estás generando una subcapa. No es necesariamente un problema, pero debe explicarlo en detalle para el OP.
richo
Funcionó, pero antes tuve que dar permiso a mi archivo "activar".
Adrian Lopez
1
¡Esto funciona en 2019! En macos tuve que cambiar el /bin/basha/usr/bin/env bash
valem
Funciona en Ubuntu 18.04 AWS EC2 en 2020. Me pregunto ¿cómo desactivo usando la misma lógica?
CSF Junior
deactivatedesde el subshell con exito Ctrl + d
Alexx Roche
10

El abastecimiento ejecuta comandos de shell en su shell actual. Cuando obtiene dentro de un script como lo está haciendo arriba, está afectando el entorno de ese script, pero cuando el script sale, los cambios de entorno se deshacen, ya que efectivamente se han salido del alcance.

Si su intención es ejecutar comandos de shell en virtualenv, puede hacerlo en su script después de obtener el script de activación. Si su intención es interactuar con un shell dentro del virtualenv, entonces puede generar un sub-shell dentro de su script que heredaría el entorno.

zigg
fuente
2

Aquí está el guión que uso a menudo. Ejecutarlo como$ source script_name

#!/bin/bash -x
PWD=`pwd`
/usr/local/bin/virtualenv --python=python3 venv
echo $PWD
activate () {
    . $PWD/venv/bin/activate
}

activate
Arena1512
fuente
1

¿Para qué sirve el origen del script bash?

  1. Si tiene la intención de cambiar entre múltiples virtualenv o ingresar un virtualenv rápidamente, ¿ha probado? virtualenvwrapper ? Proporciona muchas utilidades como workon venv, mkvirtualenv venvetc.

  2. Si acaba de ejecutar un script de Python en cierto virtualenv, utilícelo /path/to/venv/bin/python script.pypara ejecutarlo.

iMom0
fuente
De hecho, me gustaría llamar workon ...desde un script bash. (Porque quiero ejecutar más cosas después cada vez que se inicia). Sin embargo, no puedo encontrar la manera de que funcione.
Daniel B.
1

También puede hacer esto usando una subcapa para contener mejor su uso; aquí hay un ejemplo práctico:

#!/bin/bash

commandA --args

# Run commandB in a subshell and collect its output in $VAR
# NOTE
#  - PATH is only modified as an example
#  - output beyond a single value may not be captured without quoting
#  - it is important to discard (or separate) virtualenv activation stdout
#    if the stdout of commandB is to be captured
#
VAR=$(
    PATH="/opt/bin/foo:$PATH"
    . /path/to/activate > /dev/null  # activate virtualenv
    commandB  # tool from /opt/bin/ which requires virtualenv
)

# Use the output from commandB later
commandC "$VAR"

Este estilo es especialmente útil cuando

  • una versión diferente de commandAo commandCexiste bajo/opt/bin
  • commandBexiste en el sistema PATHo es muy común
  • estos comandos fallan bajo el virtualenv
  • uno necesita una variedad de virtualenvs diferentes
ti7
fuente
No olvide citar dos veces $(...)o le faltarán espacios y pestañas en el resultado.
Eric
"${VAR}"es estrictamente equivalente a "$VAR"que no necesita corchetes alrededor de las variables de shell porque las comillas dobles son en realidad más poderosas. La excepción es cuando se usan modificadores como, por ejemplo"${VAR:-default_value}"
Eric
PATH=$PATH:/opt/binnecesita una cita adecuada para manejar rutas con espacios y tabulaciones.
Eric
@Eric Gracias, aunque puedes usar el editbotón debajo de las publicaciones para sugerir cambios. Además, sepa que, si bien a menudo es un requisito e importante para la seguridad, cualquiera que a sabiendas agregue IFScaracteres PATHes un terrorista.
ti7
0

Debe utilizar varios comandos en una línea. por ejemplo:

os.system(". Projects/virenv/bin/activate && python Projects/virenv/django-project/manage.py runserver")

cuando activa su entorno virtual en una línea, creo que se olvida de otras líneas de comando y puede evitarlo utilizando varios comandos en una línea. Funcionó para mí :)

Ahmadreza Pourghodrat
fuente
0

Cuando estaba aprendiendo venv, creé un script para recordarme cómo activarlo.

#!/bin/sh
# init_venv.sh
if [ -d "./bin" ];then
  echo "[info] Ctrl+d to deactivate"
  bash -c ". bin/activate; exec /usr/bin/env bash --rcfile <(echo 'PS1=\"(venv)\${PS1}\"') -i"
fi

Esto tiene la ventaja de que cambia el indicador.

Alexx Roche
fuente