2009-04-30 5 views
2

En ce moment, j'ai un script mod_wsgi qui est structuré comme celui-ci ..mod_wsgi tampon de sortie de rendement au lieu de retour

def application(environ, start_response): 
    status = '200 OK' 
    output = 'Hello World!' 

    response_headers = [('Content-type', 'text/plain'), 
        ('Content-Length', str(len(output)))] 
    start_response(status, response_headers) 

    return [output] 

Je me demandais si quelqu'un connaît un moyen de changer cela pour fonctionner sur une base yield au lieu de return, de cette façon, je peux envoyer la page en cours de génération et non seulement une fois qu'elle est terminée, donc le chargement de la page peut aller plus vite pour l'utilisateur.

Cependant, chaque fois que j'échange la sortie pour une liste et le rendement dans l'application(), il renvoie une erreur:

TypeError: sequence of string values expected, value of type list found 
+0

Si vous êtes d'accord avec ma réponse, veuillez la choisir comme acceptée. – nosklo

Répondre

7
def application(environ, start_response): 
    status = '200 OK' 
    output = 'Hello World!' 

    response_headers = [('Content-type', 'text/plain'), 
        ('Content-Length', str(len(output)))] 
    start_response(status, response_headers) 

    yield output 

"However, whenever I swap the output for a list and yield it in the application(), it throws an error:"

Eh bien, ne donnent pas la liste. Rendement chaque élément à la place:

for part in mylist: 
    yield part 

ou si la liste est tout le contenu, il suffit:

return mylist 

Parce que la liste est déjà un itérateur et peut donner par lui-même.

+1

Hah, ouais, je suis nouveau à céder. Je vois mon erreur maintenant. : P – Ian

0

N'envoyez pas la longueur du contenu et envoyez la sortie telle que vous la dérivez. Vous n'avez pas besoin de connaître la taille de la sortie si vous n'obtenez simplement pas l'en-tête Content-Length. De cette façon, vous pouvez envoyer une partie de la réponse avant d'avoir calculé le reste.

def application(environ, start_response): 
    status = '200 OK' 
    output = 'Hello World!' 

    response_headers = [('Content-type', 'text/html')] 
    start_response(status, response_headers) 

    yield head() 
    yield part1() 
    yield part2() 
    yield part3() 
    yield "<!-- bye now! -->" 

Sinon, vous obtiendrez aucun avantage d'envoyer en morceaux, depuis la sortie de calcul est probablement la partie lente et le protocole Internet envoie la sortie en morceaux de toute façon.

Malheureusement, cela ne fonctionne pas dans le cas où, par exemple, le calcul de part2() décide que vous avez vraiment besoin de changer un en-tête (comme un cookie) ou besoin de construire d'autres structures de données en page globale - si jamais cela arrive, vous devez calculer la production totale avant d'envoyer les en-têtes, et peut aussi bien utiliser un return [output]

par exemple http://aaron.oirt.rutgers.edu/myapp/docs/W1200_1200.config_template a besoin pour construire une page structure de données globale pour les liens aux paragraphes qui s'affiche en haut de la page - la dernière sous-section doit donc être affichée avant que le premier morceau de sortie soit remis au client.

7

Notez que «rendement» doit être évité, sauf si absolument nécessaire. En particulier "rendement" sera inefficace si donnant beaucoup de petites chaînes. Cela est dû au fait que la spécification WSGI exige qu'après chaque chaîne, la réponse soit vidée. Pour Apache/mod_wsgi, le vidage signifie que chaque chaîne est expulsée à travers le système de brigade et de filtre de sortie Apache et sur le socket. En ignorant les frais généraux du système de filtre de sortie Apache, écrire beaucoup de petites chaînes sur une socket est simplement tout simplement mauvais pour commencer.

Ce problème existe également lorsqu'un tableau de chaînes est renvoyé à partir d'une application car un vidage doit également être effectué entre chaque chaîne dans le tableau. C'est parce que la chaîne est traitée comme une itérable et non comme une liste.Ainsi, pour une liste préformée de chaînes, il est préférable de joindre les chaînes individuelles en une seule grande chaîne et de renvoyer une liste contenant juste une chaîne. Cela permet également à une implémentation WSGI de générer automatiquement une longueur de contenu pour la réponse si elle n'a pas été explicitement fournie. Assurez-vous que lorsque vous joignez toutes les chaînes d'une liste, le résultat est renvoyé dans une liste. Si cela n'est pas fait et qu'à la place la chaîne est renvoyée, cette chaîne est traitée comme une itérable, où chaque élément de la chaîne est une chaîne de caractères unique. Cela entraîne un flush après chaque personnage, ce qui sera encore pire que si les chaînes n'avaient pas été jointes.