Gestión de paquetes & entornos virtuales Python con pip, virtualenv & virtualenvwrapper
lun 30 diciembre 2013, por Soulchainer
Problemática
Cuando usas Python con asiduidad, ya sea por cuestiones de desarrollo o simplemente por preferir ciertas aplicaciones construidas en este lenguaje, tarde o temprano te encuentras con un problema: las dichosas dependencias y la versionitis [1].
Consideremos los siguientes supuestos:
Estás desarrollando dos aplicaciones con Python 3.3.3.
- La primera aplicación importa la librería
wlib
, que tiene entre sus dependencias la libreríalibpeta == 1.0
, instalada globalmente en el sistema. - En la segunda aplicación necesitas usar la librería
ylib
, que requierelibpeta >= 1.5
.
Si actualizas
libpeta
de la versión 1.0 a la 1.5, para cumplir los requisitos deylib
, la primera aplicación peta. Ya la hemos liado. ¿Qué hacemos ahora?.- La primera aplicación importa la librería
Quieres probar una aplicación supercuriosa que has visto en GitHub, pero vaya: tiene un montón de dependencias, está basada en una versión de Python que no usas, muchas de sus librerías no están en los repositorios de tu distro… Y encima no trae script de desinstalación. Esto va a ser un marrón cuando quiera borrarla: si no quiero que me deje el sistema lleno de basurilla voy a tener que crearme un script o desinstalar las dependencias a manita. ¿No hay una forma más fácil de hacer esto?
pip para instalar & administrar paquetes
pip es una utilidad que nos facilita enormemente la tarea de instalar y administrar paquetes Python.
Instalación
pip requiere de setuptools para funcionar. De hecho, está diseñado para ser un reemplazo de easy_install, un módulo Python que se empaqueta junto a setuptools.
No obstante, centrándonos en Linux, pip suele estar disponible en los repositorios de las principales distribuciones, por lo que se puede instalar fácilmente via Administrador de Paquetes.
Así, en Archlinux :
$ yaourt -S python-pip
nos instalará tanto pip como setuptools de forma global en el sistema.
EDICIÓN: lo anterior instalará pip para Python 3, que es la versión por defecto en Archlinux y otras distribuciones. Por lo que si planeamos usar Pyhton 2.x, deberíamos instalar también:
$ yaourt -S python2-pip
E instalar via pip los paquetes que deseemos usar en ese entorno (globalmente)
con pip2
o pip2.7
.
Instalar paquetes
Normalmente se usa pip para instalar paquetes de PyPI [2], pero también puede usarse para instalar paquetes de otros índices, de urls de proyectos gestionados con un VCS [3], de directorios de proyectos locales y de archivos locales o remotos.
Además, también soporta la instalación de paquetes listados en archivos de requisitos (que no son más que archivos de texto plano con un requisito a satisfacer por línea), proveyéndonos así de una forma rápida y sencilla de especificar un entorno completo a instalar.
pip install [opciones] <especificación de requisito> ...
pip install [opciones] -r <archivo de requisitos> ...
pip install [opciones] [-e] <url proyecto VCS> ...
pip install [opciones] [-e] <ruta proyecto local> ...
pip install [opciones] <url/ruta archivo> ...
Veamos algunos ejemplos concretos del uso común de pip install
:
Instalación básica de un paquete de PyPI:
$ pip install nombre_paquete
Instalación de un paquete de PyPI especificando un requisito:
$ pip install 'nombre_paquete==2.5'
Aquí especificamos que queremos instalar la versión 2.5 de
nombre_paquete
. Se pueden usar, entre otros, los típicos operadores de comparación< <= != == >= >
. Se usan comillas simples o dobles para evitar que se interpreten los símbolos< >
como redirecciones.Instalación de varios paquetes mediante un archivo de requisitos:
$ pip install -r archivo_requisitos.txt
Donde
archivo_requisitos.txt
:nombre_paquete1==2.5 nombre_paquete2>0.5 nombre_paquete3!=3.1
NOTA: También se pueden instalar varios paquetes sin recurrir al uso de un archivo de requisitos:
$ pip install nombre_paquete1 nombre_paquete2 "nombre_paquete3>=1.12.24"
Desinstalar paquetes
Una vez hemos aprendido a instalar paquetes, desinstalarlos es bastante sencillo:
pip uninstall [opciones] <paquete> ...
pip uninstall [opciones] -r <archivo de requisitos> ...
Si vamos a desinstalar uno o varios paquetes y estamos absolutamente seguros de
lo que hacemos, podemos usar la opción -y
o --yes
para que no
nos pida confirmación sobre los archivos a borrar:
$ pip uninstall -y nombre_paquete
Listar paquetes & información
Tenemos dos formas de listar los paquetes instalados con pip:
Listar los paquetes en formato de requisitos.
pip freeze [opciones]
Así, sobre el entorno que tengo configurado para este blog:
(entorno)[usuario@hostname] [carpeta] $ pip freeze Jinja2==2.7.1 Markdown==2.3.1 Pygments==1.6 beautifulsoup4==4.3.2 pelican==3.3 ...
Este formato de listado resulta muy útil cuando queremos instalar los mismos paquetes en otro entorno. En ese supuesto, sólo tendríamos que hacer:
pip freeze > requisitos.txt
para obtener el archivo de requisitos; e instalarlos después en el nuevo entorno como ya vimos anteriormente.
Listar de forma ordinaria.
pip list [opciones]
Retomando el ejemplo anterior, el comando ahora devolvería:
(entorno)[usuario@hostname] [carpeta] $ pip list beautifulsoup4 (4.3.2) Jinja2 (2.7.1) Markdown (2.3.1) pelican (3.3) Pygments (1.6) ...
En este caso resulta particularmente útil la opción
-o
o--outdated
, que comprueba las versiones de los paquetes instalados e imprime una lista con los nombres de los desactualizados, enfrentando sus versiones actuales con las últimas disponibles.$ pip list -o setuptools (Current: 0.9.8 Latest: 2.0.2)
Si lo que deseamos no es listar paquetes instalados, sino obtener mayor información de los mismos, usaremos:
pip show [opciones] <paquete> ...
Por defecto, nos muestra el nombre del paquete, la versión instalada, la ruta de instalación y sus dependencias:
$ pip show pip pelican
---
Name: pip
Version: 1.4.1
Location: /ruta/de/instalacion
Requires:
---
Name: pelican
Version: 3.3
Location: /ruta/de/instalacion
Requires: feedgenerator, jinja2, pygments, docutils, pytz, blinker, unidecode, six
Podemos usar la opción -f
o --files
para obtener la lista de
todos los archivos referentes a un paquete:
$ pip show -f nombre_paquete
Buscar paquetes
Se puede buscar paquetes en PyPI desde la línea de comandos con:
pip search [opciones] <búsqueda>
Si buscamos por w3c
, por ejemplo:
$ pip search w3c
pyprov - A Python implementation of W3C PROV data model
py_w3c - Library for W3C markup validation SOAP service
w3c-validator - W3C panel for Django Debug Toolbar using requests.
...
pip es mucho más que todo esto. RTFM.
Entornos virtuales Python
Los entornos virtuales vienen a solucionar el problema planteado en el primer supuesto anterior.
Un entorno virtual Python no es más que una carpeta con una copia de Python
(enlaza a su librería estándar y añade los paquetes setuptools pip
),
donde podemos instalar los paquetes adicionales que queramos con pip,
sin miedo a crear conflictos con la instalación global. Es un entorno aislado.
Para trabajar con entornos virtuales usaremos virtualenv y virtualenvwrapper. Este último no es estrictamente necesario, pero facilita mucho el uso cotidiano del anterior, proporcionando una capa de comandos que lo vuelve imprescindible. Tanto que sólo trataremos con virtualenv durante su obligada instalación, el resto del tiempo virtualenvwrapper mediará con él por nosotros.
Instalación
Una vez tenemos instalado pip, podemos instalar ambas herramientas a través de él:
$ pip install virtualenv virtualenvwrapper
Aunque en este caso yo prefiero instalarlas con el Administrador de paquetes del sistema, para no tener que preocuparme de revisar periódicamente si hay actualizaciones y esas cosas.
$ yaourt -S python-virtualenvwrapper
Con esto es suficiente: en Archlinux este paquete tiene como dependencias los
paquetes python-virtualenv python2-virtualenv
, que corresponden a las
versiones para Python 3.x y Python 2.x de virtualenv, respectivamente.
Configuración
Como a partir de este punto es muy posible que sólo usemos pip en entornos virtuales, podemos decirle que sólo se ejecute cuando haya un entorno virtual activado. Para ello, desde consola:
export PIP_REQUIRE_VIRTUALENV=true
Pero esto sólo lo hace temporal (durante la sesión actual). Para volverlo
permanente hemos de añadir la misma línea a ~/.bashrc
[4].
También podemos añadir a nuestro ~/.bashrc
las siguientes líneas:
export WORKON_HOME=~/.virtualenvs
source /usr/bin/virtualenvwrapper.sh
La primera línea hace saber a virtualenvwrapper dónde se encuentran nuestros
entornos.
Entornos que, como podemos observar, estarán en nuestra carpeta de usuario,
dentro de una carpeta oculta llamada .virtualenvs
.
Esto sólo es necesario si vamos a guardar nuestros entornos en una ruta distinta, ya que si no declaramos WORKON_HOME
, virtualenvwrapper
asume que se encuentran en esa ubicación.
La segunda línea carga virtualenvwrapper cada vez que abrimos un terminal. Yo realmente no hago esto.
Para terminar, creamos el directorio que albergará los entornos:
$ mkdir ~/.virtualenvs
Uso básico
Desenvolverse con los entornos virtuales con virtualenvwrapper es pasmosamente simple.
Crear un entorno
Creamos entornos virtuales con mkvirtualenv
:
mkvirtualenv [-a ruta_proyecto] [-i paquete] [-r archivo_requisitos] [opciones virtualenv] NOMBRE_ENTORNO
Para simplemente crear un entorno con el intérprete Python por defecto:
$ mkvirtualenv mi_entorno
Si queremos que emplee otro intérprete, tenemos que especificárselo con la
opción -p
o --python
:
$ mkvirtualenv -p python2.7 mi_entorno
$ mkvirtualenv --python=python2.7 mi_entorno
Como se puede apreciar en la síntaxis del comando, con la opción -r
podemos indicarle un archivo de requisitos, para que instale determinados
paquetes en el entorno justo después de su creación.
Activar el entorno
Para comenzar a trabajar en un entorno, hemos de activarlo:
$ workon mi_entorno
Al activar un entorno, el prompt cambia a:
(mi_entorno)[usuario@hostname] [carpeta] $
Como un recordatorio del entorno en el que nos encontramos.
Listar entornos
Podemos listar los entornos creados hasta el momento con:
$ workon
Si lo que queremos listar es el contenido de la carpeta site-packages
del entorno actual:
(mi_entorno)$ lssitepackages
Borrar entornos
Podemos borrar entornos con:
(mi_entorno)$ rmvirtualenv otro_entorno
No podemos borrar un entorno si lo tenemos activado, tenemos que…
Desactivar el entorno
(mi_entorno)$ deactivate
Limpiar un entorno
Si sólo queremos empezar de cero con un entorno, no hace falta borrarlo, basta con limpiar todos los paquetes en él instalados:
(mi_entorno)$ wipeenv
Como bien señalé antes, esto es sólo una pequeña muestra de todo lo que virtualenvwrapper puede hacer.
Aparte del resto de comandos que virtualenvwrapper pone a nuestra
disposición, destacaría los
scripts que se ejecutan antes y después de ciertas acciones. Se encuentran
en la raíz de tu directorio WORKON_HOME
y pueden ser muy útiles.
Yo por ahora sólo empleo postmkvirtualenv
, para instalar determinado
paquete en cada entorno que creo.
Configuración extra
Como colofón, mencionar que soy algo perezoso [5] y desmemoriado
(muy desmemoriado, para qué nos vamos a engañar), y por ello tengo
definidos en mi .bashrc
una serie de alias [6] que me hacen la vida
un poco más fácil:
# Entornos virtuales (.virtualenvs) con virtualenvwrapper
# http://virtualenvwrapper.readthedocs.org/en/latest/
alias venvson='source virtualenvwrapper.sh' # activa gestor de entornos Python
alias addvenv='mkvirtualenv' # crea y activa nuevo entorno (dado el nombre)
alias addvenv2='mkvirtualenv -p /usr/bin/python2.7' # con python2.7
# "workon entorno" para activar/cambiar a entorno
# "workon" para listar los entornos
alias venvoff='deactivate' # salir del entorno
alias rmvenv='rmvirtualenv' # elimina el entorno (dado el nombre)
alias lsvenv='lssitepackages' # lista contenido carpeta site-packages venv
[1] | Una situación en la que hay muchas versiones diferentes (y posiblemente incompatibles) del mismo software, archivo o documento. |
[2] | Python Package Index (Índice de Paquetes Python). Es un gran repositorio de paquetes Python. En el momento de escribir esto lista 38300 paquetes. |
[3] | Version Control System (Sistema de Control de Versiones). Un sistema de control de versiones es una pieza de software diseñada para gestionar proyectos homónimos: almacenamiento, historial de cambios de los archivos, manejo de distintas ramas de desarrollo (versiones). |
[4] | .bashrc es el fichero de configuración de Bash (Bourne again shell), la shell (intérprete de comandos) por defecto en Linux. |
[5] | Ser perezoso no siempre es malo: a veces agudiza el ingenio :) |
[6] | Los alias de Bash son mnemónicos: términos que sustituyen cadenas de instrucciones más largas y, al mismo tiempo, resultan más fáciles de recordar. |