Comment les frameworks Web Python, WSGI et CGI s'associent

150

J'ai un compte Bluehost où je peux exécuter des scripts Python en tant que CGI. Je suppose que c'est le CGI le plus simple, car pour exécuter, je dois définir ce qui suit dans .htaccess:

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

Maintenant, chaque fois que je recherche la programmation Web avec Python, j'entends beaucoup parler de WSGI et de la façon dont la plupart des frameworks l'utilisent. Mais je ne comprends tout simplement pas comment tout cela s'emboîte, en particulier lorsque mon serveur Web est donné (Apache fonctionnant sur la machine d'un hôte) et pas quelque chose avec lequel je peux vraiment jouer (sauf définir des .htaccesscommandes).

Comment WSGI , CGI et les frameworks sont-ils tous connectés? Que dois-je savoir, installer et faire si je veux exécuter un framework Web (par exemple web.py ou CherryPy ) sur ma configuration CGI de base? Comment installer le support WSGI?

Eli Bendersky
la source

Réponses:

242

Comment WSGI, CGI et les frameworks sont-ils tous connectés?

Apache écoute sur le port 80. Il reçoit une requête HTTP. Il analyse la demande pour trouver un moyen de répondre. Apache a BEAUCOUP de choix pour répondre. Une façon de répondre consiste à utiliser CGI pour exécuter un script. Une autre façon de répondre est de simplement servir un fichier.

Dans le cas de CGI, Apache prépare un environnement et appelle le script via le protocole CGI. Il s'agit d'une situation standard Unix Fork / Exec - le sous-processus CGI hérite d'un environnement OS comprenant le socket et stdout. Le sous-processus CGI écrit une réponse, qui revient à Apache; Apache envoie cette réponse au navigateur.

CGI est primitif et ennuyeux. Principalement parce qu'il forge un sous-processus pour chaque demande, et que le sous-processus doit quitter ou fermer stdout et stderr pour signifier la fin de la réponse.

WSGI est une interface basée sur le modèle de conception CGI. Ce n'est pas nécessairement CGI - il ne doit pas forcer un sous-processus pour chaque requête. Cela peut être CGI, mais ce n'est pas obligatoire.

WSGI ajoute au modèle de conception CGI de plusieurs manières importantes. Il analyse les en-têtes de requête HTTP pour vous et les ajoute à l'environnement. Il fournit toute entrée orientée POST sous la forme d'un objet de type fichier dans l'environnement. Il vous fournit également une fonction qui formulera la réponse, vous évitant ainsi de nombreux détails de mise en forme.

Que dois-je savoir / installer / faire si je veux exécuter un framework Web (par exemple web.py ou cherrypy) sur ma configuration CGI de base?

Rappelez-vous que forger un sous-processus coûte cher. Il existe deux façons de contourner ce problème.

  1. Embarquez mod_wsgi ou mod_pythonincorpore Python dans Apache; aucun processus n'est fourchu. Apache exécute directement l'application Django.

  2. Daemon mod_wsgi ou mod_fastcgipermet à Apache d'interagir avec un démon séparé (ou "processus de longue durée"), en utilisant le protocole WSGI. Vous démarrez votre processus Django de longue durée, puis vous configurez le mod_fastcgi d'Apache pour communiquer avec ce processus.

Notez que cela mod_wsgipeut fonctionner dans les deux modes: intégré ou démon.

Lorsque vous lirez sur mod_fastcgi, vous verrez que Django utilise flup pour créer une interface compatible WSGI à partir des informations fournies par mod_fastcgi. Le pipeline fonctionne comme ça.

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

Django a plusieurs "django.core.handlers" pour les différentes interfaces.

Pour mod_fastcgi, Django fournit un manage.py runfcgiqui intègre FLUP et le gestionnaire.

Pour mod_wsgi, il existe un gestionnaire principal pour cela.

Comment installer le support WSGI?

Suivez ces instructions.

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

Pour le fond voir ceci

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

S.Lott
la source
4
Je ne peux pas installer mod_wsgi car je suis sur un hébergement mutualisé. Tout ce que j'ai, c'est le support fcgi. Comment puis-je toujours exécuter des applications WSGI via celui-ci?
Eli Bendersky
3
+1 C'est une excellente réponse et répond à beaucoup de questions (mais pas à toutes) que j'ai en tête. Cette réponse n'est toujours pas complète. Vous avez bien expliqué CGI et WSGI, mais quelle est la relation et les différences entre FASTCGI et WSGI? Ce qui est mieux? Comment travaillent-ils? Comment mod_python est-il entré en scène?
griffes
14
S.Lott, au lieu de se plaindre du moment où les gens demandent ce qui est "meilleur", pourquoi ne pas simplement dire "mod_wsgi est meilleur que X, fastcgi est meilleur pour Y", et si l'OP a des questions plus spécifiques, ils poseront.
Gregg Lind
7
@Greg Lind: Pourquoi ne pas simplement dire "mod_wsgi est meilleur que X, fastcgi est meilleur pour Y"? Parce que ce n'est pas très facile à faire. Il existe des dizaines de facteurs de qualité non fonctionnels qui sont des éléments des ensembles X et Y. Il est difficile de tous les énumérer. Il est de loin, beaucoup mieux pour les gens de poser des questions spécifiques sur les facteurs de qualité pertinents.
S.Lott
4
Juste pour les notes: l'option runfcgi est obsolète depuis la version 1.7 et le support FastCGI a été supprimé dans Django 1.9.
OBu
58

Je pense que la réponse de Florian répond à la partie de votre question sur "qu'est-ce que WSGI", surtout si vous lisez le PEP .

Quant aux questions que vous posez vers la fin:

WSGI, CGI, FastCGI, etc. sont tous des protocoles permettant à un serveur Web d' exécuter du code et de fournir le contenu dynamique produit. Comparez cela à la diffusion Web statique, où un fichier HTML brut est essentiellement livré tel quel au client.

CGI, FastCGI et SCGI sont indépendants du langage. Vous pouvez écrire des scripts CGI en Perl, Python, C, bash, peu importe. CGI définit quel exécutable sera appelé, en fonction de l'URL, et comment il sera appelé: les arguments et l'environnement. Il définit également la manière dont la valeur de retour doit être renvoyée au serveur Web une fois que votre exécutable est terminé. Les variations sont essentiellement des optimisations pour pouvoir gérer plus de requêtes, réduire la latence, etc. le concept de base est le même.

WSGI est uniquement Python. Plutôt qu'un protocole indépendant du langage, une signature de fonction standard est définie:

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']

Il s'agit d'une application WSGI complète (si limitée). Un serveur Web prenant en charge WSGI (tel qu'Apache avec mod_wsgi) peut appeler cette fonction chaque fois qu'une demande arrive.

La raison pour laquelle c'est si génial est que nous pouvons éviter l'étape compliquée de la conversion d'un HTTP GET / POST à ​​CGI en Python, et revenir à la fin. C'est une liaison beaucoup plus directe, propre et efficace.

Il est également beaucoup plus facile d'avoir des frameworks de longue durée exécutés derrière des serveurs Web, si tout ce qui doit être fait pour une requête est un appel de fonction. Avec CGI simple, vous devrez démarrer l'ensemble de votre framework pour chaque demande individuelle.

Pour avoir le support WSGI, vous devez avoir installé un module WSGI (comme mod_wsgi ) ou utiliser un serveur Web avec WSGI intégré (comme CherryPy ). Si aucun de ceux-ci n'est possible, vous pouvez utiliser le pont CGI-WSGI donné dans le PEP.

James Brady
la source
3
Quelle était l'idée stupide de ne pas rendre le langage WSGI indépendant? Quel est le point alors? Pourrait aussi simplement expédier l'ensemble de Python en tant que module Apache.
Salman von Abbas
2
@SalmanPK Je pense que c'est juste un compromis. Il n'est certainement pas facile (voire impossible) de créer un protocole indépendant du langage qui puisse être utilisé en implémentant simplement une fonction dans la langue choisie.
phunehehe
21

Vous pouvez exécuter WSGI sur CGI comme le montre Pep333 à titre d'exemple. Cependant, chaque fois qu'il y a une demande, un nouvel interpréteur Python est démarré et tout le contexte (connexions à la base de données, etc.) doit être construit, ce qui prend du temps.

Le mieux si vous voulez exécuter WSGI serait si votre hôte installait mod_wsgi et effectuait une configuration appropriée pour reporter le contrôle à une de vos applications.

Flup est une autre façon de fonctionner avec WSGI pour tout serveur Web pouvant parler FCGI , SCGI ou AJP. D'après mon expérience, seul FCGI fonctionne vraiment, et il peut être utilisé dans Apache via mod_fastcgi ou si vous pouvez exécuter un démon Python séparé avec mod_proxy_fcgi .

WSGI est un protocole un peu comme CGI, qui définit un ensemble de règles sur la façon dont le serveur Web et le code Python peuvent interagir, il est défini comme Pep333 . Cela permet à de nombreux serveurs Web différents d'utiliser de nombreux frameworks et applications différents utilisant le même protocole d'application. Ceci est très bénéfique et le rend si utile.

Florian Bösch
la source
3
Est-ce que l'exécution de WSGI sur CGI sert à "flup"? Comment flup est-il connecté au schéma?
Eli Bendersky
7

Si vous n'êtes pas clair sur tous les termes de cet espace, et admettons-le, c'est un acronyme déroutant, il y a aussi un bon lecteur de fond sous la forme d'un HOWTO python officiel qui discute de CGI vs FastCGI vs WSGI et ainsi de suite. sur: http://docs.python.org/howto/webservers.html

Richard Boardman
la source
2
L'URL est obsolète, je pense que celle-ci est mise à jour: docs.python.org/2.7/howto/webservers.html
Stefaan
Excellent matériel :) Il faut lire cette introduction officielle avec la réponse acceptée.
Rick
4

C'est une simple couche d'abstraction pour Python, semblable à la spécification Servlet pour Java. Alors que CGI est vraiment de bas niveau et dépose simplement des éléments dans l'environnement de processus et les entrées / sorties standard, les deux spécifications ci-dessus modélisent la requête et la réponse http comme des constructions dans le langage. Mon impression cependant est qu'en Python, les gens ne se sont pas tout à fait installés sur des implémentations de facto, vous avez donc un mélange d'implémentations de référence et d'autres bibliothèques de type utilitaire qui fournissent d'autres choses avec le support WSGI (par exemple Paste). Bien sûr, je peux me tromper, je suis un nouveau venu en Python. La communauté "web scripting" aborde le problème sous un autre angle (hébergement mutualisé, héritage CGI,

Aaron
la source