2013-10-09 4 views
1

J'essaie de mettre des calculs lents dans les threads, et obtenir une erreur "Request.write appelé sur une demande après Request.finish a été appelé."Twisted Erreur: Request.write appelé sur une demande après que Request.finish a été appelé

J'ai déjà regardé les réponses et j'ai trouvé exactement la même question, mais la solution ne fonctionnait pas pour moi. S'il vous plaît donnez votre avis.

from twisted.web.server import Site, NOT_DONE_YET 
from twisted.web.resource import Resource 
from twisted.internet import reactor, threads 
from twisted.python import log 

import sys 
import time 


def SlowComputation(): 
    time.sleep(10) 
    return "Lang Computation Result" 


def FastComputation(): 
    return "Fast Computation Result" 


class PerformComputation(Resource): 
    def Success(self, request): 
     request.write('Success') 
     request.finish() 

    def Failure(self, request): 
     request.write('Failure') 
     request.finish() 

    def render_GET(self, request): 
     if 'fast' in request.args: 
      d = threads.deferToThread(FastComputation) 
      d.addCallback(self.Success(request)) 
      return NOT_DONE_YET 
     if 'slow' in request.args: 
      d = threads.deferToThread(SlowComputation) 
      d.addCallback(self.Success(request)) 
      return NOT_DONE_YET 


log.startLogging(sys.stdout) 
root = Resource() 
root.putChild("calculate", PerformComputation()) 
factory = Site(root) 
reactor.listenTCP(8880, factory, interface='localhost') 
reactor.run() 

Répondre

3

Ce:

d.addCallback(self.Success(request)) 

est le même que:

temp = self.Success(request) 
d.addCallback(temp) 

qui, compte tenu de la définition de Success est le même que:

request.write('Success') 
request.finish() 
temp = None 
d.addCallback(None) 

Cela échoue probablement avec Request.write a appelé une requête après l'appel de Request.finish. car d.addCallback(None) déclenche une exception et le serveur essaie de signaler l'erreur en tant que réponse. Cependant, puisque finish a déjà été appelé, il ne peut pas écrire l'erreur.

La méthode correcte pour ajouter un rappel à Deferred avec un argument supplémentaire est d.addCallback(self.Success, request). Callbacks sur un Deferredtoujours sont transmis le résultat de la Deferred comme premier argument, bien que - si la signature correcte pour Success est:

def Success(self, result, request): 
    ... 
+1

Merci Jean-Paul, votre contribution est très précieuse. En outre, j'ai figuré ma faute de frappe dans le code. –

Questions connexes