Cherrypy 2.2 con Apache2
Hace tiempo que quiero empezar a programar python para entorno web, y un ex-compañero de trabajo de servidores.com me ha explicado algunas cosas (el resto lo estoy aprendiendo del Dive into python).
Entre otras cosas,me aconsejó usar Cherrypy como framework y Cheetah como gestor de plantillas. El problema lo he tenido para hacer funcionar el conjunto Cherrypy-Apache, ya que el framework de cherrypy incorpora un servidor web que recibe las peticiones en un puerto propio, y Apache debe gestionar el traslado de URLs (si se quiere que quede bonito). Es posible hacerlo con mod_python o con scgi, pero una manera simple y eficiente de hacerlo es con mod_rewrite, que es como yo lo he hecho.
Aclaro también (muy importante) que el editor wysiwyg de Wordpress no me guarda las anidaciones en el código, así que debereis hacer caso al editor de texto si detecta el highlight y hace autoindent (vim lo hace perfectamente) porque es CRUCIAL, la diferencia entre que los ejemplos funcionen y que no funcionen.
Para empezar se necesita cherrypy, que puede instalarse fácilmente usando el sistema de paquetes propio de cada distribución, o bien obtenerse del site oficial, sección downloads. Una vez instalado el framework, se puede implementar un sencillo “Hello world” para probar que funciona (vim hello.py):
# Hello World en python import cherrypy class helloworld: def index(self): return "Hello World" index.exposed = True cherrypy.root = helloworld() cherrypy.server.start()
Ahora basta con lanzar la miniaplicación con cherrypy
python hello.py
Escupirá un poco de debug y finalmente dirá que está escuchando en el puerto 8080. Lanzando un navegador contra http://localhost:8080 se ve el hello world. Ahora lo que falta es incorporarlo en Apache.
Se edita el virtualhost que se quiera destinar a esta aplicacion y se aplican las reglas de mod_rewrite que redirigen la URL de apache al servidor de cherrypy
RewriteEngine on RewriteRule ^(.*) http://localhost:8080$1 [P] ServerAdmin me@home.net ServerName localhost ServerAlias 127.0.0.1 ErrorLog /var/log/apache/localhost-error.log CustomLog /var/log/apache/localhost-acces.log common
De esta forma al lanzar el navegador contra http://localhost veremos el Hello Wold, pero Cherrypy cambiará las cabeceras de forma que el navegador mostrará la URL http://localhost:8080/. Para evitarlo es necesario cambiar algunos parámetros de la configuración del servidor de Cherrypy, que pueden personalizarse para cada aplicación en concreto directamente desde el código de la aplicación, o bien cargando un fichero externo con el desglose de parámetros que la aplicación debe sobreescribir a la config original. El segundo caso es más limpio, de modo que simplemente se especifica a la aplicación el fichero que debe cargar… hay que modificarla para qeu quede de la siguiente forma:
# Hello World en python import cherrypy class helloworld: def index(self): return "Hello World" index.exposed = True cherrypy.root = helloworld() # server extra configuration cherrypy.config.update(file = "server.cfg") cherrypy.server.start()
Evidentemente acto seguido se debe escribir el fichero de configuración, que siguiendo la sintaxis del código de la aplicación debe estar situada en la raíz del path relativo, es decir en el mismo directorio que la aplicación (vim server.cfg).
[global] server.socketPort = 8080 server.threadPool = 10 server.environment = "production" base_url_filter.on = True base_url_filter.use_x_forwarded_host = True
Ahora Ya sepuede lanzar de nuevo el servidor (python hello.py) y comprobar que apuntando el navegador a http://localhost se ve el Hello World sin que la URL cambie.
Ahora bien, ¿qué pasa si se quieren programar dos aplicaciones dentro de un mismo servidor Cherrypy, y que cada una responda a un virtualhost diferente?
Pues pasa que en este caso pueden programarse las aplicaciones por separado, y desde un servidor principal importar las clases y montarlas (publicarlas) en paths relativos. Una vez hecho eso, desde los virtualhosts de apache puede usarse la sintaxis de mod_rewrite para enviar las peticiones a un lugar u otro. Sirva para el ejemplo un “Hello World” y un “Goodbye World”.
1. hello.py
# Hello World en python class helloworld: def index(self): return "Hello World" index.exposed = True
2. bye.py
# Goodbye World en python class byeworld: def index(self): return "Goodbye World" index.exposed = True
3. main.py
# Fichero principal de la aplicación import cherrypy from hello import helloworld from bye import byeworld cherrypy.tree.mount (helloworld(), baseurl="/hello") cherrypy.tree.mount (byeworld(), baseurl="/bye") cherrypy.config.update(file = "server.cfg") cherrypy.server.start()
Ahora ya se puede ejecutar el servidor (python main.py), y al lanzar el navegador apuntando a http://localhost/hello se ve el “Hello World”, y al apuntarlo a http://localhost/bye se ve el “GoodBye World”. Lo que interesa ahora es que apuntando el navegador a una dirección ejecute una aplicación, y apuntando a otra dirección diferente ejecute la otra aplicación. Esto ya se hace desde apache.
Suponiendo que la configuración se hace para un dominio de ejemplo somedomain.net , el virtualhost que muestra el Hello World se configuraría de la siguiente forma:
RewriteEngine on RewriteRule ^(.*) http://localhost:8080/hello$1 [P] ServerAdmin info@somedomain.net ServerName hello.somedomain.net ErrorLog /var/log/apache/hello-error.log CustomLog /var/log/apache/hello-acces.log common
Y de la misma forma, el que muestra el Goodbye World sería como sigue
RewriteEngine on RewriteRule ^(.*) http://localhost:8080/bye$1 [P] ServerAdmin info@somedomain.net ServerName bye.somedomain.net ErrorLog /var/log/apache/bye-error.log CustomLog /var/log/apache/bye-acces.log common
Como puede entenderse del ejemplo, apuntando el navegador a http://hello.somedomain.net se verá el “Hello Wolrd”, y apuntándolo a http://bye.somedomain.net se verá el “Goodbye World”.
Pero no sólo llega aquí la cosa. Si os fijais, el fichero main.py es el servidor principal que sirve las dos aplicaciones. Este servidor está cargando el fichero que sobreescribe la configuración general de Cherrypy para retocar el retorno de las cabeceras a apache. Bien, pues es posible modificar la configuración de forma independiente para cada aplicación dentro de un mismo servidor Cherrypy. Para hacer la prueba voy a implementar un path /test que en el caso de cada aplicación por separado mostrará el contenido de un fichero diferente.
mkdir static/ echo "Static hello" > static/hello.txt echo "Static Goodbye" > static/bye.txt
Se debe crear un fichero de configuración para cada aplicación
1. hello.cfg
[/test] static_filter.on = True static_filter.file = "static/hello.txt"
2. bye.cfg
[/test] static_filter.on = True static_filter.file = "static/bye.txt"
También es necesario añadir dos líneas al código del servidor (main.py) porque Cherrypy busca un punto inexistente al final de los nombres de ficheros estáticos, algo que supongo que se corregirá en futuras versiones. Aparte, debe pasarse como parámetro la configuración específica de cada aplicación al montarlas en la raíz. Debe quedar así (vim main.py):
# Fichero principal de la aplicación
import cherrypy
from hello import helloworld
from bye import byeworld
from os.path import abspath
cherrypy.config.update({"static_filter.root": abspath(".")})
cherrypy.tree.mount (helloworld(), baseurl="/hello", conf="hello.cfg")
cherrypy.tree.mount (byeworld(), baseurl="/bye", conf="bye.cfg")
cherrypy.config.update(file = "server.cfg")
cherrypy.server.start()
Así, el servidor carga su propia configuración para la modificación de los parámetros globales que le permiten devolver las cabeceras correctas a Apache, y cada aplicación por separado incluye una configuración que especifica el fichero a mostrar cuando el navegador acceda a /test. Para hacer la prueba se puede apuntar el navegador a http://hello.somedomain.net/test y a http://bye.somedomain.net/test, y se comprueba que en el primer caso muestra el texto del Hello World estático, y en el segundo caso muestra el texto del Goodbye World estático.
La verdad es que esto es una minucia con lo que se puede aprender en la documentación oficial de Cherrypy, pero de momento es un comienzo, y desde luego a mí me supone el punto de partida para pasar de php a python. Imagino que a partir de ahora de vez en cuando daré la tabarra con cosas que vaya aprendiendo sobre python. De entrada en cuanto instale Cheetah y aplique la primera plantilla vendré a explicar como lo he hecho.

Viernes, 12 Mayo 2006, a las 8:19 pm
El framework de moda para Python es Django.
Miércoles, 19 Julio 2006, a las 4:15 am
Buen articulo.
Estoy usando Turbogears, que esta basado en CherryPy.
Si lo conoces me gustaria me indiques que tengo que modificar para lanzar dos app de TG desde el mismo servidor.
Tambien Utilizo apache2, virtualhost y mod_proxy.
De todas formas vere si puedo adaptar tu articulo, la doc en ingles me da problemas y en castellano hay poco
Sábado, 8 Marzo 2008, a las 9:55 pm
Muy buen articulo, navegando me tope con tu pag. !
en realidad no se python :(, aun .
Y gracias por el link hacia una referencia para el lenguage.
saludos !