2 Stimmen

Verdrillte nicht-blockierende Methode - wie geht das?

Mein Code sieht folgendermaßen aus:

... # class Site(Resource)
def render_POST(self,request)
   otherclass.doAssync(request.args)
   print '1'
   return "done" #that returns the HTTP response, always the same.

...

def doAssync(self,msg):
    d = defer.Deferred()
    reactor.callLater(0,self.doStuff,d,msg)
    d.addCallback(self.sucess)

def doStuff(self,d,msg):
    # do some stuff
    time.sleep(2)  #just for example
    d.callback('ok')

def sucess(msg):
    print msg

Das Ergebnis:

1

ok

So weit, so gut, aber die HTTP-Antwort (return 'done') erfolgt erst nach der Verzögerung (time.sleep(2)). Ich kann das feststellen, weil der Browser 2 Sekunden lang "lädt".

Was mache ich falsch?

0 Stimmen

Ich habe eine Antwort gefunden: stackoverflow.com/questions/6759115/

2 Stimmen

Seien Sie vorsichtig, in welchen Threads Sie Twisted APIs - einschließlich Deferreds, d.h. d.callback - verwenden. Diese Version des Codes verwendet d.callback im falschen Thread. Dies führt dazu, dass alle Rückrufe im falschen Thread ausgeführt werden, was wahrscheinlich etwas kaputt macht, sobald Sie mehr tun als nur das Ergebnis zu drucken.

4voto

Thomas Wouters Punkte 124421

Was Sie falsch machen, ist die Ausführung eines blockierenden Aufrufs ( time.sleep(2) ), während Twisted erwartet, dass Sie nur nicht-blockierende Operationen durchführen. Dinge, die nicht warten. Denn Sie haben diese time.sleep(2) kann Twisted nichts anderes tun, während diese Funktion schläft. Also kann es auch keine Daten an den Browser senden.

Im Fall von time.sleep(2) würden Sie diese durch eine andere ersetzen reactor.callLater anrufen. Angenommen, Sie wollten tatsächlich die time.sleep(2) Aufruf zu einer anderen blockierenden Operation, wie man das beheben kann, hängt von der Operation ab. Wenn Sie die Operation auf eine nicht blockierende Weise durchführen können, tun Sie das. Für viele solcher Operationen (wie z.B. Datenbankinteraktion) bietet Twisted bereits nicht-blockierende Alternativen. Wenn das, was Sie tun, keine nicht-blockierende Schnittstelle hat und Twisted keine Alternative dazu hat, müssen Sie den Code in einem separaten Thread ausführen (z.B. mit twisted.internet.threads.deferToThread ), obwohl dies voraussetzt, dass Ihr Code tatsächlich thread-sicher ist.

1 Stimmen

Kann er also die reactor.callLater(...) mit einer deferToThread(...) ?

0 Stimmen

Wenn Sie eine reactor.callInThread(global_function) und global_function hat eine blockierende Operation wie eine lokale Datei lesen und verarbeiten es Inhalt. solange die global_function ausgeführt wird, scheint die Fabrik-Thread als Antworten deutlich verlangsamen betroffen sein, wissen Sie, warum?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X