A la hora de crear un sitio web con Python, la opción más sencilla es usar un framework y algunas de las muchas aplicaciones y bibliotecas ya disponibles. Pero ¿qué sucede si usamos una biblioteca que no está disponible en la cuenta de alojamiento que contratamos?
La respuesta a esta pregunta es virtualenv. Se trata de un paquete que permite instalar otros paquetes y bibliotecas en un directorio cualquiera, sin depender de la carpeta global de Python o heredando los paquetes instalados en ella.
En mi cuenta de Valcato tuve que utilizar virtualenv para instalar django-cms y el blog Zinnia, ya que no estaban entre los paquetes disponibles.
En mi caso, virtualenv no estaba instalado en la carpeta global, pero
esto no es un problema: basta con descargar el archivo .zip y
descomprimirlo en una carpeta cualquiera del servidor. Luego simplemente
ejecutando python virtualenv.py
funciona perfectamente.
Para crear el entorno virtual, debemos conectarnos a la cuenta de
alojamiento vía SSH, usando PuTTY o un programa similar. Esto es
necesario porque se requiere ejecutar comandos.
Una vez conectados y en la línea de comandos del servidor, basta con
ejecutar el comando virtualenv
con un parámetro que indica el nombre
de la carpeta en la que se copiarán los archivos necesarios:
# virtualenv mi_entorno_virtual
Para evitar problemas, conviene tener dos puntos en consideración:
Luego de crearlo, y antes de poder utilizarlo, hay que activar el entorno virtual recién creado. Esto hace que las siguientes llamadas a python o a programas hechos en python encuentren las carpetas del entorno virtual y sea posible instalar paquetes allí. La activación requiere otro comando simple:
# . mi_entorno_virtual/bin/activate
Es importante ejecutar el comando anterior tal cual se muestra,
incluyendo el punto inicial (el # es simplemente una forma genérica de
representar el indicador de la línea de comandos o prompt). Obviamente
cambia el nombre de la carpeta donde el entorno virtual fue creado. Lo
importante es que luego de esto, las llamadas a python ejecutarán
mi_entorno_virtual/bin/python
, y
mi_entorno_virtual/lib/python/site-packages estará en sys.path
(de
forma simple: lo que esté en mi_entorno_virtual tendrá precedencia
sobre lo que esté en la carpeta global de Python en el sistema)
Una vez activado el entorno virtual, se dispone de los comandos pip
y easy_install
para instalar paquetes de python en él, sin afectar
lo que esté instalado en el directorio global. En mi caso necesitaba
instalar django-blog-zinnia, así que simplemente usé la siguiente orden:
# pip install django-blog-zinnia
pip no solamente instala el paquete indicado sino que instala también sus dependencias, por lo que una vez finalizada su tarea ya queda todo listo para usar.
Para poder usar el entorno virtual desde la línea de comandos, se
requiere ejecutar el programa bin/activate
, pero FastCGI no tiene
una línea de comandos. Entonces ¿cómo indicarle que utilice los paquetes
allí instalados? La respuesta está en la biblioteca estándar de Python,
y es el módulo site
.
El método addsitedir del módulo site
sirve para lo que necesitamos:
agregar una nueva carpeta al entorno de ejecución de Python para que sea
considerada como otra site-packages.
Si ya estás usando Django con FastCGI, seguramente tengas un archivo con extensión .fcgi y con contenido similar a lo siguiente:
1 #!/usr/bin/env python2.6
2 import sys, os
3
4 sys.path.insert(1, "/ruta/a/tu/proyecto/django")
5 os.environ['DJANGO_SETTINGS_MODULE'] = "proyecto.settings"
6
7 from django.core.servers.fastcgi import runfastcgi
8 runfastcgi(method="threaded", daemonize="false")
Entonces, para que FastCGI encuentre y use los paquetes instalados en el
entorno virtual, se importa el módulo y se invoca a addsitedir
antes
de hacer el sys.path.insert
:
import site
site.addsitedir('/ruta/al/entorno/virtual/lib/python2.6/site-packages')
Si no hay conflictos de paquetes entre el directorio global y el entorno
virtual, lo anterior es suficiente para que todo funcione correctamente.
Sin embargo, en caso de conflictos pueden surgir problemas. Esto es
porque addsitedir
agrega los directorios del entorno virtual
después de los directorios globales en sys.path
, y sin un orden
predefinido. Si tu archivo .fcgi
utiliza addsitedir
y un día de
repente algo no funciona, o funciona mal, podría ser producto de un
conflicto de versiones del mismo paquete entre el entorno virtual y el
entorno global del servidor.
El problema está más detallado en el sitio de mod_wsgi. La solución
es básicamente reordenar sys.path
para que los directorios agregados por
addsitedir
aparezcan primero. El resultado final en el archivo de
FastCGI es algo como esto:
1 #!/usr/bin/env python2.6
2 import sys, os, site
3
4 # Remember original sys.path.
5 prev_sys_path = sys.path[:]
6
7 # Add each new site-packages directory.
8 site.addsitedir('/ruta_al_entorno_virtual/elcodiguero-env/lib/python2.6/site-packages')
9
10 # Reorder sys.path so new directories at the front.
11 new_sys_path = []
12 for item in sys.path:
13 if item not in prev_sys_path:
14 new_sys_path.append(item)
15 sys.path.remove(item)
16 sys.path[:0] = new_sys_path
17
18 sys.path.insert(1, "/ruta_al/proyecto_django/")
19 os.environ['DJANGO_SETTINGS_MODULE'] = "proyecto.settings"
20
21 from django.core.servers.fastcgi import runfastcgi
22 runfastcgi(method="threaded", daemonize="false")
Una vez cumplidos estos pasos, nuestro sitio Django tendrá disponibles todos los paquetes que queramos instalar en el entorno virtual.
Activa Javascript para para cargar los comentarios, basados en DISQUS
El Blog de ElCodiguero funciona sobre Pelican