Cómo los marcos web de Python, WSGI y CGI encajan

150

Tengo una cuenta de Bluehost donde puedo ejecutar scripts de Python como CGI. Supongo que es el CGI más simple, porque para ejecutar tengo que definir lo siguiente en .htaccess:

Options +ExecCGI
AddType text/html py
AddHandler cgi-script .py

Ahora, cada vez que busco programación web con Python, escucho mucho sobre WSGI y cómo la mayoría de los frameworks lo usan. Pero no entiendo cómo encaja todo, especialmente cuando se proporciona mi servidor web (Apache se ejecuta en la máquina de un host) y no es algo con lo que realmente pueda jugar (excepto definir .htaccesscomandos).

¿Cómo están conectados WSGI , CGI y los marcos? ¿Qué necesito saber, instalar y hacer si quiero ejecutar un marco web (digamos web.py o CherryPy ) en mi configuración básica de CGI? ¿Cómo instalar el soporte WSGI?

Eli Bendersky
fuente

Respuestas:

242

¿Cómo están conectados WSGI, CGI y los marcos?

Apache escucha en el puerto 80. Recibe una solicitud HTTP. Analiza la solicitud para encontrar una manera de responder. Apache tiene MUCHAS opciones para responder. Una forma de responder es usar CGI para ejecutar un script. Otra forma de responder es simplemente servir un archivo.

En el caso de CGI, Apache prepara un entorno e invoca el script a través del protocolo CGI. Esta es una situación estándar de Unix Fork / Exec: el subproceso CGI hereda un entorno de sistema operativo que incluye el socket y la salida estándar. El subproceso CGI escribe una respuesta, que vuelve a Apache; Apache envía esta respuesta al navegador.

CGI es primitivo y molesto. Principalmente porque bifurca un subproceso para cada solicitud, y el subproceso debe salir o cerrar stdout y stderr para indicar el final de la respuesta.

WSGI es una interfaz que se basa en el patrón de diseño CGI. No es necesariamente CGI, no tiene que bifurcar un subproceso para cada solicitud. Puede ser CGI, pero no tiene que serlo.

WSGI se suma al patrón de diseño CGI de varias maneras importantes. Analiza los encabezados de solicitud HTTP por usted y los agrega al entorno. Proporciona cualquier entrada orientada a POST como un objeto similar a un archivo en el entorno. También le proporciona una función que formulará la respuesta, lo que le ahorrará muchos detalles de formato.

¿Qué necesito saber / instalar / hacer si quiero ejecutar un marco web (digamos web.py o cherrypy) en mi configuración básica de CGI?

Recuerde que bifurcar un subproceso es costoso. Hay dos formas de solucionar esto.

  1. Embebido mod_wsgi o mod_pythonincrusta Python dentro de Apache; Ningún proceso se bifurca. Apache ejecuta la aplicación Django directamente.

  2. Daemon mod_wsgi o mod_fastcgipermite que Apache interactúe con un demonio separado (o "proceso de larga ejecución"), utilizando el protocolo WSGI. Comienza su proceso de Django de larga duración, luego configura el mod_fastcgi de Apache para comunicarse con este proceso.

Tenga en cuenta que mod_wsgipuede funcionar en cualquier modo: incrustado o demonio.

Cuando lea sobre mod_fastcgi, verá que Django usa flup para crear una interfaz compatible con WSGI a partir de la información proporcionada por mod_fastcgi. La tubería funciona así.

Apache -> mod_fastcgi -> FLUP (via FastCGI protocol) -> Django (via WSGI protocol)

Django tiene varios "django.core.handlers" para las distintas interfaces.

Para mod_fastcgi, Django proporciona un manage.py runfcgique integra FLUP y el controlador.

Para mod_wsgi, hay un controlador principal para esto.

¿Cómo instalar el soporte WSGI?

Siga estas instrucciones.

https://code.google.com/archive/p/modwsgi/wikis/IntegrationWithDjango.wiki

Para el fondo vea esto

http://docs.djangoproject.com/en/dev/howto/deployment/#howto-deployment-index

S.Lott
fuente
44
No puedo instalar mod_wsgi porque estoy en un alojamiento compartido. Todo lo que tengo es soporte fcgi. ¿Cómo puedo ejecutar aplicaciones WSGI a través de él?
Eli Bendersky
3
+1 Esa es una excelente respuesta y responde muchas (pero no todas) preguntas que tengo en mente. Esta respuesta aún no está completa. Explicó bien sobre CGI y WSGI, pero ¿cuál es la relación y las diferencias entre FASTCGI y WSGI? ¿Cual es mejor? ¿Cómo trabajan? ¿Cómo entró mod_python en la imagen?
garras
14
S.Lott, en lugar de quejarse cuando la gente pregunta cuál es "mejor", ¿por qué no simplemente decir "mod_wsgi es mejor como X, fastcgi es mejor para Y", y si el OP tiene preguntas más específicas, preguntarán.
Gregg Lind
77
@ Greg Lind: ¿Por qué no simplemente decir "mod_wsgi es mejor como X, fastcgi es mejor para Y"? Porque no es muy fácil de hacer. Hay docenas de factores de calidad no funcionales que son elementos de los conjuntos X e Y. Es difícil enumerarlos a todos. Es mucho, mucho mejor para la gente hacer preguntas específicas sobre los factores de calidad que son relevantes.
S.Lott
44
Solo para las notas: la opción runfcgi está en desuso desde la versión 1.7 y el soporte FastCGI se eliminó en Django 1.9.
OBu
58

Creo que la respuesta de Florian responde la parte de su pregunta sobre "qué es WSGI", especialmente si lee el PEP .

En cuanto a las preguntas que planteas hacia el final:

WSGI, CGI, FastCGI, etc. son todos protocolos para que un servidor web ejecute código y entregue el contenido dinámico que se produce. Compare esto con el servicio web estático, donde básicamente se entrega un archivo HTML simple al cliente.

CGI, FastCGI y SCGI son independientes del lenguaje. Puede escribir scripts CGI en Perl, Python, C, bash, lo que sea. CGI define qué ejecutable se llamará, en función de la URL, y cómo se llamará: los argumentos y el entorno. También define cómo debe devolverse el valor de retorno al servidor web una vez que finalice su ejecutable. Las variaciones son básicamente optimizaciones para poder manejar más solicitudes, reducir la latencia, etc. El concepto básico es el mismo.

WSGI es solo Python. En lugar de un protocolo agnóstico de lenguaje, se define una firma de función estándar:

def simple_app(environ, start_response):
    """Simplest possible application object"""
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    return ['Hello world!\n']

Esa es una aplicación WSGI completa (aunque limitada). Un servidor web con soporte WSGI (como Apache con mod_wsgi) puede invocar esta función siempre que llegue una solicitud.

La razón por la que esto es tan genial es que podemos evitar el desordenado paso de convertir de un HTTP GET / POST a CGI a Python, y viceversa al salir. Es un enlace mucho más directo, limpio y eficiente.

También hace que sea mucho más fácil tener frameworks de larga duración ejecutándose detrás de los servidores web, si todo lo que se necesita hacer para una solicitud es una llamada a la función. Con CGI simple, tendría que iniciar todo su marco para cada solicitud individual.

Para tener soporte WSGI, necesitará haber instalado un módulo WSGI (como mod_wsgi ), o usar un servidor web con WSGI incorporado (como CherryPy ). Si ninguno de estos es posible, puede usar el puente CGI-WSGI que se proporciona en el PEP.

James Brady
fuente
3
¿De quién fue la estúpida idea de no hacer que el lenguaje WSGI fuera agnóstico? ¿Cuál es el punto entonces? También podría enviar todo Python como un módulo Apache.
Salman von Abbas
2
@SalmanPK Creo que es solo una compensación. Seguramente no es fácil (si no imposible) hacer un protocolo independiente del idioma que pueda usarse simplemente implementando una función en el idioma elegido.
phunehehe
21

Puede ejecutar WSGI sobre CGI como lo demuestra Pep333 como ejemplo. Sin embargo, cada vez que hay una solicitud, se inicia un nuevo intérprete de Python y es necesario construir todo el contexto (conexiones de base de datos, etc.), lo que lleva tiempo.

Lo mejor si desea ejecutar WSGI sería si su host instalara mod_wsgi e hiciera una configuración adecuada para diferir el control a una aplicación suya.

Flup es otra forma de ejecutar WSGI para cualquier servidor web que pueda hablar FCGI , SCGI o AJP. Desde mi experiencia, solo FCGI realmente funciona, y puede usarse en Apache a través de mod_fastcgi o si puede ejecutar un demonio Python separado con mod_proxy_fcgi .

WSGI es un protocolo muy similar a CGI, que define un conjunto de reglas sobre cómo el servidor web y el código Python pueden interactuar, se define como Pep333 . Hace posible que muchos servidores web diferentes puedan usar diferentes marcos y aplicaciones usando el mismo protocolo de aplicación. Esto es muy beneficioso y lo hace muy útil.

Florian Bösch
fuente
3
¿Está ejecutando WSGI sobre CGI para qué sirve "flup"? ¿Cómo se conecta flup al esquema?
Eli Bendersky
7

Si no está claro en todos los términos en este espacio, y admitámoslo, es un acrónimo confuso, también hay un buen lector de antecedentes en forma de un COMO oficial de Python que discute CGI vs. FastCGI vs. WSGI y así en: http://docs.python.org/howto/webservers.html

Richard Boardman
fuente
2
La URL está desactualizada, creo que está actualizada: docs.python.org/2.7/howto/webservers.html
Stefaan
Gran material :) Uno debería leer esta introducción oficial junto con la respuesta aceptada.
Rick
4

Es una capa de abstracción simple para Python, similar a la especificación de Servlet para Java. Mientras que CGI tiene un nivel realmente bajo y solo descarga cosas en el entorno del proceso y la entrada / salida estándar, las dos especificaciones anteriores modelan la solicitud y la respuesta http como construcciones en el lenguaje. Sin embargo, mi impresión es que en Python la gente no se ha decidido por las implementaciones de facto, por lo que tiene una combinación de implementaciones de referencia y otras bibliotecas de tipo de utilidad que proporcionan otras cosas junto con el soporte de WSGI (por ejemplo, Pegar). Por supuesto que podría estar equivocado, soy un recién llegado a Python. La comunidad de "secuencias de comandos web" está llegando al problema desde una dirección diferente (hosting compartido, legado de CGI,

aaron
fuente