Original article: How to manage multiple Python versions and virtual environments

Actualización de enero del 2019: Si estás regresando a este blog después de actualizar a macOS Mojave, por favor consulta este tema de github para solucionar el problema común de pyenv 'zlib no disponible'.

Antes de empezar, repasemos brevemente los términos usados en el título:

  • Múltiples versiones de Python: Diferentes instalaciones de Python en la misma máquina, por ejemplo, 2.7 y 3.4.
  • Entornos virtuales: entornos independientes aislados que pueden tener tanto una versión específica de Python como de cualesquiera paquetes específicos de proyecto instalados en ellos, sin afectar a otros proyectos.

Aquí se verán tres herramientas diferentes para trabajar con estos, y cuándo puede que se necesite cada una. Exploremos los casos de uso para:

  • venv / pyvenv
  • pyenv
  • pyenv-virtualenv

Si se está usando una sola versión de Python, como la versión 3.3+, y se quieren administrar diferentes entornos virtuales, entonces venv es todo lo que se necesita.

Si se quieren usar múltiples versiones de Python en 3.3+, con o sin entornos virtuales, entonces hay que leer sobre pyenv.

Si también se quiere trabajar con Python 2, entonces pyenv-virtualenv es una herramienta a considerar.

venv

Desde Python 3.3+ el paquete venv está incluido. Es ideal para crear entornos virtuales ligeros.

Hasta Python 3.6 un script llamado pyvenv también se incluyó como envoltorio de  venv, pero ya es obsoleto. Se eliminará por completo en Python 3.8. La misma funcionalidad está disponible cuando se usa venv, y cualquier documentación existente debe ser actualizada. Para quien esté interesado, puede leer las razones detrás de la depreciación de pyvenv.  

venv se usa para crear un nuevo entorno mediante la terminal de comandos:

$ python3 -m venv nombre-del-directorio-a-crear

se activa con:

$ source nombre-dado/bin/activate

y se desactiva simplemente con:

$ deactivate

Si se necesita eliminar el entorno por completo después de desactivarlo, se puede ejecutar:

$ rm -r nombre-dado

Por defecto, el entorno que se crea será de la versión actual de Python que se está usando. Si se está escribiendo documentación y se quiere la seguridad adicional de que la versión correcta de Python está siendo usada por el lector, se puede especificar el número de versión mayor y menor en el comando de este modo:

$ python3.6 -m venv example-three-six

Si el lector utiliza una versión distinta de la 3.6, entonces el comando no tendrá éxito y lo indicará en su mensaje de error. Sin embargo, cualquier versión de parche (por ejemplo 3.6.4) funcionará.

Cuando el entorno está activo, cualquier paquete puede ser instalado ahí mediante pip de manera normal. Por defecto, el entorno recién creado no incluirá ningún paquete ya instalado en la computadora. Como el propio pip no estará necesariamente instalado en la computadora, se recomienda que primero se actualice pip a la última versión usando pip install --upgrade pip.

Los proyectos comúnmente tendrán un archivo requirements.txt especificando sus dependencias. El siguiente comando pip install -r requirements.txt instalará rápidamente todos los paquetes al recién creado entorno virtual. Esos paquetes solo existirán en dicho entorno virtual. No estarán disponible cuando se desactive el entorno virtual, pero persistirán cuando se reactive nuevamente.

Si no se necesita usar versiones adicionales de Python, entonces esto es todo lo que se requiere para crear entornos virtuales aislados y especificos del proyecto.

pyenv

Si se desea usar múltiples versiones de Python en un solo equipo, entonces pyenv es una herramienta comúnmente usada para instalar y cambiar entre versiones. Esto no se debe confundir con el script depreciado pyvenv mencionado anteriormente. No viene de paquete con Python, y debe ser instalado por separado.

La documentación de pyenv incluye una amplia descripción de cómo funciona, por lo que aquí se verá simplemente como usarlo.

Primero se necesita instalarlo. Si se usa Mac OS X, esto se consigue usando Homebrew, de lo contrario hay que considerar otras opciones de instalación.

$ brew update
$ brew install pyenv

Después, se agrega lo siguiente al final de nuestros scripts de shell para permitir que pyenv cambie automáticamente las versiones:

eval "$(pyenv init -)"

Para hacerlo, abre el script de shell en uso mediante $ ~/.zshrc, $ ~/.bashrc o $ ~/.bash_profile y copia y pega la línea anterior.

El ejecutar pyenv versions mostrará qué versiones de Python están actualmente instaladas, con un * al lado de la que está actualmente en uso. pyenv version muestra esto directamente, y python --version puede ser usado para verificarlo.

Para instalar una versión adicional, como la 3.4.0, simplemente se usa pyenv install 3.4.0.

pyenv busca en cuatro lugares para decidir cuál versión de Python usar, en orden de prioridad:

  1. La variable de entorno PYENV_VERSION (si se especifica). Se puede usar el comando pyenv shell para establecer esta variable de entorno en la sesión de shell actual.
  2. El archivo .python-version específico de la aplicación en el directorio actual (si está presente). Se puede modificar el archivo .python-version del directorio actual con el comando pyenv local.
  3. El primer archivo .python-version encontrado (si hay alguno) buscando en cada directorio padre, hasta llegar a la raíz del sistema de archivos.
  4. El archivo de versión global. Se puede modificar este archivo usando el comando pyenv global. Si el archivo de versión global no está presente, pyenv asume que se quiere usar el Python del "sistema". (En otras palabras, cualquier versión que se ejecutaría si pyenv no estuviera en el PATH.)

Al crear un nuevo proyecto que va a usar Python 3.6.4, entonces pyenv local 3.6.4 se ejecutaría en su directorio raíz. De este modo, se establecería tanto la versión como la creación de un archivo .python-version , para que los equipos de otros colaboradores lo recojan.

La descripción completa de los comandos pyenv es algo para marcar.

pyenv y venv

Cuando se trabaja con Python 3.3+ ahora se sabe cómo instalar y cambiar entre diferentes versiones de Python, así como crear nuevos entornos virtuales.

Como ejemplo, digamos que se está configurando un proyecto que va a usar Python 3.4.

Primero se podría establecer la versión local usando pyenv local 3.4.0.

Si luego se ejecuta python3 -m venv proyecto-de-ejemplo un nuevo entorno virtual se crearía bajo proyecto-de-ejemplo, usando Python 3.4.0 habilitado localmente.

Se activa usando source proyecto-de-ejemplo/bin/activate y se puede empezar a trabajar.

Luego se podría documentar opcionalmente que un colaborador debería usar python3.4 -m venv <nombre>. Esto significa que incluso si un colaborador no estaba usando pyenv, el comando python3.4 marcaría error si su versión de Python no era la misma versión mayor y menor (3 y 4), como se pretendía.

Como alternativa, se podría elegir a especificar simplemente que la versión 3.4.0 se iba a ser usado, e instruir a python3 -m venv <nombre>. Si se cree que cualquier versión mayor a 3.4 es aceptable, entonces también se puede optar por usar python3 sobre python3.4, ya que si el colaborador estuviera usando 3.6 entonces también recibiría un error. Esta es una decisión específica de proyecto.

pyenv-virtualenv

pyenv puede ser usado para instalar ambas versiones de Python 2 y 3. Sin embargo, como se ha visto, venv está limitado a las versiones de Python superiores a la 3.3.

pyenv-virtualenv es una herramienta para crear entornos virtuales integrada con pyenv, y funciona para todas las versiones de Python. Aun así se recomienda usar el venv oficial de Python donde sea posible. Pero si, por ejemplo, se está creando un entorno virtual basado en 2.7.13, entonces esto complementa a pyenv.

Esto también funciona bien con los ambientes conda de Anaconda y Miniconda si ya se están usando. También existe una herramienta llamada virtualenv . No se cubre aquí, pero hay un enlace al final.

Después de instalar pyenv puede ser instalado usando Homebrew (u otras alternativas) de la siguiente manera:

$ brew install pyenv-virtualenv

Después, en .zshrc, .bashrc, o .bash_profile (dependiendo de la shell que se use) se agregan estas líneas al final:

eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

Esto permite a pyenv activar y desactivar entornos automáticamente al mover directorios.

Para crear un nuevo entorno virtual, se usa:

$ pyenv virtualenv <version> <nombre-a-dar>

// por ejemplo

$ pyenv virtualenv 2.7.10 mi-entorno-virtual-2.7.10

Los entornos existentes se pueden listar con:

$ pyenv virtualenvs

Activar/desactivar con:

$ pyenv activate <nombre>
$ pyenv deactivate

Al momento de escribir esto, cuando se usa activate la advertencia prompt changing will be removed from future release se muestra en pantalla. Esto es de esperarse y se refiere únicamente al (nombre-entorno) siendo desplegado en el shell, no al uso del comando activate en sí.

La instalación de requerimientos funciona como se describe en  venv. A diferencia de venv, un comando rm -r no es necesario para remover un entorno, pues existe un comando uninstall.

Reflexiones finales

Entre estas tres herramientas, se tiene la habilidad de colaborar en cualquier proyecto, sin importar la versión de Python o de las dependencias requeridas. También se sabe ahora cómo documentar las instrucciones de configuración para que otros las usen para cualquier proyecto en el que se trabaje.

También se puede ver el razonamiento detrás de cuál conjunto usar, ya que no todos los desarrolladores necesitarán los tres.

Espero esto haya sido de ayuda y es una referencia útil en combinación con la documentación cuyos enlaces se muestran a continuación.

¡Gracias por leer!