PDF de programación - Clase 8: Python en la web - Curso Python en 8 clases

Imágen de pdf Clase 8: Python en la web - Curso Python en 8 clases

Clase 8: Python en la web - Curso Python en 8 clasesgráfica de visualizaciones

Publicado el 8 de Octubre del 2020
765 visualizaciones desde el 8 de Octubre del 2020
308,0 KB
13 paginas
Creado hace 14a (22/04/2010)
Curso Python en 8 clases

Clase 8: Python en la web

Autor: Sebastián Bassi

Versión:
Licencia: Creative Commons BY-NC-SA 2.5. (ver texto completo)

1.5

Introducción
Hay distintos modos de ejecutar código Python en el servidor. Cada modo tiene sus ventajas y
desventajas. El método mas fácil es via CGI, que ejecuta una instancia de Python cada vez que se lo
llama. Es a su vez el método mas lento. El código Python puede correrse "embebido" en el HTML al estilo
PHP, aunque no se lo recomienda debido a que el código resultante es díficil de mantener. Para evitar
tener que levantar un interprete cada vez que se ejecuta una página hecha dinámicamente con Python,
existen alternativas como mod_python y WSGI.

En esta clase veremos los fundamentos de cada método hasta llegar a usar un web framework completo
como web2py.
CGI

Configurando el servidor web para CGI
Basicamente hay que indicar el archivo donde se van a ejecutar los scripts, la extensión de los mismos y
un alias para no mostrar el path a los scripts.

Si el directorio de scripts se encuentra en /var/www/apache2-default/cgi-bin/, tenemos que incluir las
siguientes lineas en el archivo de configuración de Apache:

<Directory /var/www/apache2-default/cgi-bin>
Options +ExecCGI
</Directory>

La extensión se indica asi:

AddHandler cgi-script .py

El alias se indica con la directiva ScriptAlias:

ScriptAlias /cgi-bin/ /var/www/apache2-default/cgi-bin/

¡No olvidar!

Hay que especificar que el script tenga permiso de ejecución:

chmod a+x MyScript.py

Ejemplo de código en CGI:

#!/usr/bin/env python

import time
print("Content-Type: text/html\n")
print("<html><head><title>Test page</title></head><body>")
print("<h1>HELLO WORLD!</h1>")
print("Local time: %s"%time.asctime(time.localtime()))
print("</body></html>")

Este código genera el siguiente HTML:

<html><head><title>Test page</title></head><body>
<h1>HELLO WORLD!</h1>
Local time: Mon Apr 12 15:11:06 2010
</body></html>

(ver pastecode.com.ar/cgi-bin/test1.cgi.)

Si bien el resultado no aporta mucho porque no tiene interactividad, sirve para comprobar que el servidor
está preparado para correr aplicaciones Python.

Página generada dinámicamente con datos provistos por el
usuario
Una manera típica de ingresar datos es vía un form de HTML:

<html><head><title>Formulario muy simple</title></head>
<body>
<form action='saludos.cgi' method='post'>
Tu nombre: <input type='text' name='username'> <p>
<input type='submit' value='Enviar'>
</form></body></html>

Este form es mostrado de esta manera:

El siguiente código procesa los datos ingresados:

#!/usr/bin/env python

import cgi
print "Content-Type: text/html\n"
form = cgi.FieldStorage()
name = form.getvalue("username","NN")
print("<html><head><title>Un script CGI</title></head>")
print("<body><h2>Hola %s</h2></body></html>"%name)

Por lo que obtenemos una respuesta como esta:

Nota: Para ver los errores via HTML, usar cgitb.enable() (usarlo solo en diseño, no en producción).
Mod_Python
El problema principal con CGI es que cada vez que llamamos a una página de este tipo, el interprete de
Python se ejecuta. Esto no escala bien debido a los requerimientos de RAM y CPU que convella levantar
un interprete por cada request. Otro problema asociado con CGI es la velocidad de ejecución (que es
baja por la razón citada).

Una manera de evitar estos inconvenientes es tener un interprete corriendo permanentemente y ejecutar
en él todas las peticiones. Esto es provisto por el módulo de Apache mod_python.

Con Mod_Python se puede ejecutar 1200 request/s contra 23 request/s como en CGI.

Configurando el servidor web para Mod_Python
Instalación en Linux:

apt-get install libapache-mod-python2.5

Luego hay que modificar el archivo de configuración de Apache de la siguiente manera:

<Directory /var/www/apache2-default>
AddHandler mod_python .py
PythonHandler mptest
PythonDebug On
</Directory>

Note que mptest es el nombre de la aplicación que se encargará de la petición. Se puede cambiar.
Entonces la aplicación se llama mptest.py y se encuentra en el directorio /var/www/apache2-default.

Ejemplo de uso:

#!/usr/bin/env python
from mod_python import apache
from mod_python.util import FieldStorage

def chargeandprop(AAseq):
# ..RESUMIDO..
return (c,p)

def handler(req):
req.content_type='text/html'
fs = dict(FieldStorage(req))
charge,pvalue = chargeandprop(fs['seq'])
html = '<html><body>Titulo:%s<br/>'\
'Tu secuencia:<br/>%s<br/>'\

'Carga neta:%s<br/>'\
%(fs['title'],fs['seq'],charge)
req.write(html)
if fs['prop']=="y":
html = "Proporcion: %.2f "%(pvalue)
req.write(html)
req.write("<br/></body></html>")
return apache.OK

Notar las diferencias con CGI.

Para mas información sobre Mod_Python: modpython.org
Mod_Python con Publisher
Se muestra Publisher porque muestra practicas actuales en desarrollo web.

Para usar Publisher hay que modificar el archivo de configuración de Apache:

<Directory /var/www/apache2-default>
SetHandler mod_python
PythonHandler mod_python.publisher
PythonDebug On
</Directory>

En este archivo se establece que todos los archivos de ese directorio serán tratado con Mod_Python.
Ahora no importa el nombre del archivo (todos los archivos serán tratados con Publisher) pero hay que
especificar la función en el URL:

<form action='/apache2-default/handler.py/netc' method='POST'>

Veamos el mismo programa con Publisher:

def chargeandprop(AAseq):
# ..RESUMIDO..
return (c,p)

def netc(req,seq,title,prop):
req.content_type = 'text/html'
charge,propval = chargeandprop(seq)
html = '<html><body>Titulo:%s<br/>'\
'Tu secuencia:<br/>%s<br/>'\
'Carga neta:%s<br/>'\
%(title,seq,charge)
req.write(html)
if prop=="y":
html = "Proportion of charged AA: %.2f" %propval
req.write(html)
req.write("<br/></body></html>")
return None

Las diferencias mas importantes pasan por las variables, el modo de llamar a la función y que tiene
caracteristicas de mas alto nivel.

WSGI
Hay varios frameworks de aplicaciones web que limitan las opciones de web servers (los pares
aplicaciones/web server suelen ser fijos). En JAVA hay un "servlet API" que hace que cualquier
aplicación que funcione sobre esa API puede andar en cualquier servidor que soporta dicha API. Por esta
razón se crea WSGI (ver PEP 333), para tener una interface común para desarrollar aplicaciones web.

Preparando el servidor para WSGI
Se puede bajar el módulo de code.google.com/p/modwsgi o desde
libapache2-mod-wsgi.

los

repositorios como

Una vez instalado, hay que agregar estas lineas en el archivo de configuración de Apache:

WSGIScriptAlias webpath path_en_servidor
WSGIScriptAlias / /var/www/sitepath/htdocs/test.wsgi

La primera linea indica que path_en_servidor será el path que recibirá todas las peticiones mientras que
en la segunda se especifica que los pedidos a / serán manejados por el script indicado (test.wsgi).

Webserver WSGI incorporado

Desde Python 2.5 hay un servidor WSGI incluido. Con 3 líneas de código podemos tener un
servidor web funcionado:

from wsgiref.simple_server import make_server
server = make_server('localhost', 8888, application)
server.serve_forever()

Este servidor es útil para diseño y pruebas, pero no fue diseñado para ser usado en producción
por limitaciones de escala y seguridad.

El uso de WSGI "puro" implica usar código de bajo nivel. Veamos un "Hola mundo!":

def application(environ, start_response):
status = '200 OK'
output = "<html><head><title>WSGI</title></head>"\
"<body>Hola mundo!</body></html>"
response_headers = [('Content-type', 'text/html'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return output

application es una funcion que el servidor llama en cada petición. Sus parametros son environ (un
diccionario con las variables) y start_response (función que devuelve los encabezados HTTP).

Esto puede evitarse usando middleware (componentes intermedios entre WSGI y el programa del
usuario). Como WSGI es parte de Python, hay muchos middleware disponibles.
(ver:
wsgi.org/wsgi/Middleware_and_Utilities)

Yaro como ejemplo de middleware
Yaro es un middleware para WSGI, se baja desde lukearno.com/projects o usando easy_install.

Primero un "Hola mundo" en Yaro:

from yaro import Yaro

def _application(req):
output = "<html><head><title>HW WSGI</title></head>"\
"<body>Hola mundo!</body></html>"
return output

application = Yaro(_application)

Comparado con el código anterior se nota que es de mas alto nivel.

Ahora veamos una aplicación que usa mas opciones de Yaro, incluyendo selector, otro middleware del
mismo autor.

#!/usr/bin/env python

from selector import Selector
from yaro import Yaro

rootdir = '/var/www/mywebsite/htdocs/'

def index(req):
return open(rootdir+'form.html').read()

def _chargeandprop(AAseq):
# ..RESUMIDO..
return (c,p)

def netc(req):
seq = req.form.get('seq','')
title = req.form.get('title','')
prop = req.form.get('prop','')
charge,propval = _chargeandprop(seq)
html = '<html><body>Titulo:%s<br/>'\
'Tu secuencia:<br/>%s<br/>'\
'Carga neta:%s<br/>'\
%(title,seq,charge)
yield html
if prop=="y":
yield "Proporcion: %.2f"%propval
yield "<br/></body></html>"

s = Selector(wrap=Yaro)
s.add('/', GET=index)
s.add('/netc', POST=netc)
application = s

Ver código completo en http://py3.us/57

Seguridad: La web es el "salvaje Oeste"

Siempre hay que tener en cuenta que los usuarios pueden ingresar datos de manera inesperada,
pero esto es mas importante en las aplicaciones online. No solo
  • Links de descarga
http://lwp-l.com/pdf18342

Comentarios de: Clase 8: Python en la web - Curso Python en 8 clases (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios...
CerrarCerrar
CerrarCerrar
Cerrar

Tienes que ser un usuario registrado para poder insertar imágenes, archivos y/o videos.

Puedes registrarte o validarte desde aquí.

Codigo
Negrita
Subrayado
Tachado
Cursiva
Insertar enlace
Imagen externa
Emoticon
Tabular
Centrar
Titulo
Linea
Disminuir
Aumentar
Vista preliminar
sonreir
dientes
lengua
guiño
enfadado
confundido
llorar
avergonzado
sorprendido
triste
sol
estrella
jarra
camara
taza de cafe
email
beso
bombilla
amor
mal
bien
Es necesario revisar y aceptar las políticas de privacidad