Web Server Gateway Interface

WSGI es una interface simple y universal entre los servidores web y las aplicaciones web o frameworks (ver más en PEP 333)

WSGI es similar a la especificación Java Servlet o ASP/ASP.NET. En general, es mucho más simple que dichas especificaciones, y se basa en el estandard CGI con mejoras "pitónicas" para hacerla reentrante, persistente, etc.

Resumen de la Especificación

Ejemplo

# Aqui va mi 'Hola PyAr!, pero con WSGI, una maravilla de Python.

from wsgiref.simple_server import make_server

def hello(environ, start_response):
    start_response('200 OK',[('Content-type','text/plain')])
    return ['Hola PyAr!']
    
httpd = make_server('',8000, hello).serve_forever()

(copiado de un mail "hello-word" de la lista)

Variables de entorno (diccionario {{{environ}}})

El diccionario environ que se recibe con cada pedido HTTP, contiene las variables estándard de la especificación CGI, entre ellas:

Configuración apache + mod_python

mod_python tiene varios handlers o "controladores" (ver documentación):

Igualmente, estos Handlers no son compatibles con WSGI, por eso no recomendaría usar ninguno de ellos directamente, sino a través del wrapper WSGI (con ModPythonGateway) que es un handler "propio" que traduce las peticiones al estandar WSGI. Es algo mucho mas estandar, valga la redundancia, y el día de mañana se puede usar cualquier servidor compatible con python, no solo apache.

Además, puede utilizarse directamente mod_wsgi (ver siguiente sección).

Ejemplos de configuración (tanto en /etc/apache2/... en un archivo .htaccess en el mismo directorio):

  # handler Publisher:
  #  se ejecutará cualquier archivo .py del directorio, llamando a la función de la url:
  #  http://www.mysite.com/hello.py/say  ejecutara el script hello.py, funcion say
  <Directory /var/www/html/python/>
      SetHandler mod_python
      PythonHandler mod_python.publisher
      PythonDebug On
  </Directory>
  
  # Handler PSP:
  #  se ejecutará cualquier archivo .psp (código python embebido en texto html)
  <Directory /var/www/html/psp/>
     AddHandler mod_python .psp
     PythonHandler mod_python.psp
  </Directory>

  # Handler CGI:
  #  se ejecutará los scripts .py (scripts normales de python) simil linea de comandos
  <Directory /var/www/cgi-bin/>
     SetHandler mod_python
     PythonHandler mod_python.cgihandler
     Options ExecCGI
  </Directory>

  # handler propio:
  #  se ejecuta el archivo myscript.py función handler(req) 
  <Directory /mywebdir>
       AddHandler mod_python .py
       PythonHandler myscript
       PythonDebug On
  </Directory>

Para configurar una aplicación wsgi en mod_python:

SetHandler python-program
PythonHandler modpython_gateway::handler
PythonOption wsgi.application app::WSGIApp
PythonPath "['C:/Archivos de programa/Apache Software Foundation/Apache2.2/htdocs/app'] + sys.path"
PythonOption SCRIPT_NAME /app

Descripción:

Configuración apache + mod_wsgi

Para usar WSGI directamente desde apache, existe mod_wsgi, que es un módulo mas reciente, totalmente codificado en C para una mejor performance y estabilidad, que simplifica y resuelve las carencias de mod_python:

Ejemplo 1: ejecutar en el mismo proceso que apache (no independiente, estilo mod_python/php/etc.). En este caso se mapea la url /app al script wsgi app.py:

WSGIScriptAlias /app /usr/local/apache/app.py

Ejemplo 2: ejecutar en un proceso (interprete) independiente con un usuario arbitrario diferente de apache (estilo FastCGI, mejorando seguridad y performance):

WSGIDaemonProcess site-1 user=trac group=trac threads=25
WSGIScriptAlias /site-1 /usr/local/apache/app.py
<Directory /usr/local/apache>
WSGIProcessGroup site-1
WSGIApplicationGroup %{GLOBAL}
</Directory>

Configuración lighttpd + wsgi

Ejemplo "avanzado"

Con respecto a la diferencia con PHP/PSP, la mayoría de las aplicaciones web en python tienen un solo punto de entrada (un solo .py), que funciona como "despachador", dependiendo de que url te piden, se llama a una función o a otra (generalmente se usa la variable de entorno SCRIPT_NAME o similar, o directamente usar cherrypy, django, turbogears, etc., para que ruteen las peticiones a las clases/funciones que correspondan)

Ejemplo muy simple con WSGI:

def App(environ, start_response):
        "Punto de entrada WSGI"
        if environ['SCRIPT_NAME'].endswith("xxxx"):
                respuesta_html = xxxx(environ)
        elif environ['SCRIPT_NAME'].endswith("yyyy"):
                respuesta_html = yyyy(environ)
        else:
                respuesta_html = "<html><body><p>la url es 
inválida!</p></body></html>"
        start_response ("200 Ok", [('Content-Type','text/html')])
        yield respuesta_html

Entonces, si te llaman www.tuservidor.com/aplicacion/xxxx haces una cosa (xxxx), mientras que si llaman a www.tuservidor.com/aplicacion/yyyy haces otra (yyyy). En comparación con php/psp, sería como llamar a www.tuservidor.com/aplicacion.psp?funcion=xxxx o www.tuservidor.com/aplicacion.psp?funcion=yyyy.

Esto es un poco mas difícil de entender, pero a la larga es mas flexible porque no te limita a tener un archivo (estructura "física") para cada dirección (estructura "lógica"), limpiando un poco la url de extensiones .py, signos de interrogación, etc. , haciéndolas mas fáciles de entender para el usuario.

WSGI (última edición 2009-04-20 18:34:48 efectuada por localhost)

USLA