Ich bin dabei, Coroutine von Tornado zu verstehen, also lassen Sie uns alles einfach halten und je mehr Code Sie einfügen, desto besser.Tornado Coroutine - Benutzerdefinierte Funktion
Was ich will ist, meine hausgemachte Funktion async zu machen.
Alle Beispiele, die ich in der Dokumentation finden konnte, fallen unter den gleichen "versteckten" Teil: AsyncHTTPClient. Ich suche keinen HTTP-Anruf. Also bitte gib mir kein Beispiel mit dieser Klasse. Ich bin daran interessiert, etwas von Grund auf neu zu erstellen. Ich habe alle Möglichkeiten auf Tornado coroutine
ausprobiert Vorerst habe ich mit einem Bash-Schlaf getestet. Hier ist der Code:
import tornado.web
import tornado.httpserver
import tornado.gen
import tornado.concurrent
import subprocess
import os
@tornado.gen.coroutine
def letswait():
fut = tornado.concurrent.Future()
subprocess.check_output(["sleep", "5"])
fut.set_result(42)
return fut
class TestHandler1(tornado.web.RequestHandler):
@tornado.gen.coroutine
def get(self):
value = yield letswait()
self.render("test.html", num=value)
class TestHandler2(tornado.web.RequestHandler):
def get(self):
self.render("test.html", num=66)
class Application(tornado.web.Application):
def __init__(self):
DIRNAME = os.path.dirname(__file__)
STATIC_PATH = os.path.join(DIRNAME, '../static')
TEMPLATE_PATH = os.path.join(DIRNAME, '../template')
sets = {
"template_path":TEMPLATE_PATH,
"static_path":STATIC_PATH,
"debug":True,
}
tornado.web.Application.__init__(self, [
(r"/test1", TestHandler1),
(r"/test2", TestHandler2),
], **sets)
def main():
http_server = tornado.httpserver.HTTPServer(Application())
http_server.listen(8888)
print "Let s start"
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
Aber wenn ich test1 besuchen dann brauche ich für den Anruf warten, um zurückzukehren, bevor ich test2 zugreifen können. Nach dem, was ich verstanden habe, muss ich gen.sleep(5)
verwenden. Aber das ist nur ein Beispiel. Lassen Sie uns sagen, anstatt sleep 5
on bash laufen zu lassen, ich laufen das dauert einige Zeit zu laufen.
Mir wurde gesagt, "diese Funktion ist nicht asynchron". Also meine Frage ist, wie mache ich eine benutzerdefinierte Funktion asynchron?
EDIT: Nach ein wenig suchen, habe ich gesehen, es gibt Tornado.Process https://gist.github.com/FZambia/5756470 hier verwendet werden. Aber mein Subprozess kommt von einer dritten Partei, also ist es nicht wirklich etwas, das ich überschreiben kann. Also meine Frage ist auch, wie integriere ich 3rd-Party-Bibliotheken mit diesem gen.coroutine System?
LÖSUNG: Durch den Kommentaren unten ich eine Lösung haben:
import tornado.web
import tornado.httpserver
import tornado.gen
import tornado.concurrent
import subprocess
import os
from concurrent import futures
# Create a threadpool, and this can be shared around different python files
# which will not re-create 10 threadpools when we call it.
# we can a handful of executors for running synchronous tasks
# Create a 10 thread threadpool that we can use to call any synchronous/blocking functions
executor = futures.ThreadPoolExecutor(10)
def letswait():
result_future = tornado.concurrent.Future()
subprocess.check_output(["sleep", "5"])
result_future.set_result(42)
return result_future
class TestHandler1(tornado.web.RequestHandler):
@tornado.gen.coroutine
def get(self):
value = yield executor.submit(letswait)
self.render("test.html", num=value)
class TestHandler2(tornado.web.RequestHandler):
def get(self):
self.render("test.html", num=66)
class Application(tornado.web.Application):
def __init__(self):
DIRNAME = os.path.dirname(__file__)
STATIC_PATH = os.path.join(DIRNAME, '../static')
TEMPLATE_PATH = os.path.join(DIRNAME, '../template')
sets = {
"template_path":TEMPLATE_PATH,
"static_path":STATIC_PATH,
"debug":True,
}
tornado.web.Application.__init__(self, [
(r"/test1", TestHandler1),
(r"/test2", TestHandler2),
], **sets)
def main():
http_server = tornado.httpserver.HTTPServer(Application())
http_server.listen(8888)
print "Let s start"
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
Können Sie versuchen, die Datei .result() zu entfernen? Das war mein Fehler. Der Ertrag sollte automatisch zum Ergebnis führen. Möglicherweise warten Sie auf das Ergebnis() und es wird blockiert. – user1157751