J'ai une application tornade et je veux utiliser une bibliothèque de blocage pour accomplir quelque chose. Dans les cas où il n'est pas possible de réécrire la bibliothèque de manière asynchrone, comment l'exécuter en tornade? Par exemple, j'aimerais pouvoir mettre un décorateur @asynchronous
sur un gestionnaire de requêtes, en commençant une fonction longue qui retournera une réponse une fois que c'est fait. Je ne peux pas simplement mettre un rappel. L'exemple le plus simple est bien sûr de savoir quelle est la bonne façon de dormir pendant 10 secondes sans bloquer le seul fil de la tornade?Exécution du code de blocage dans Tornado
Répondre
Il semble que ce que je voulais était simplement créer un nouveau thread/processus, et que l'acte même de rappeler à une tornade qui doit être fait avec IOLoop.instance().add_callback
Plus d'informations sont disponibles here
J'ai posté une question sur la performance de ce script. http://stackoverflow.com/questions/14306360/performance-of-asynchronous-request-handler-with-blocking-tasks-handled-by-work –
Essayez cet exemple ci-dessous.
import tornado.ioloop
import tornado.web
import time
class MainHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self, request):
if request is None:
self.application.go = False
self.write("Waiting for GET @ http://localhost:8888/go...<br>")
self.flush()
self._do_wait()
else:
self.application.go = True
self.finish('Thanks!')
def _do_wait(self, timeout_trys=10):
if self.application.go:
self.write('Finish')
self.finish()
else:
self.write("Sleeping 2 second, timeout_trys=%s<br>" % timeout_trys)
self.flush()
tornado.ioloop.IOLoop.instance().add_timeout(time.time() + 2,
lambda: self._do_wait(timeout_trys-1))
application = tornado.web.Application([
(r"/(\w+)?", MainHandler),
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
merci, mais je pense que ce que je cherchais, c'est plus comme je l'ai montré dans ma réponse ici – abyx
@abyx grande trouvaille! –
Le code de la réponse acceptée fait référence à is available on SO.
Une autre approche est détaillée dans un article de blog here, avec a full working gist. Voici un nouvel affichage du code à partir de l'essentiel:
from concurrent.futures import ThreadPoolExecutor
from functools import partial, wraps
import time
import tornado.ioloop
import tornado.web
EXECUTOR = ThreadPoolExecutor(max_workers=4)
def unblock(f):
@tornado.web.asynchronous
@wraps(f)
def wrapper(*args, **kwargs):
self = args[0]
def callback(future):
self.write(future.result())
self.finish()
EXECUTOR.submit(
partial(f, *args, **kwargs)
).add_done_callback(
lambda future: tornado.ioloop.IOLoop.instance().add_callback(
partial(callback, future)))
return wrapper
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world %s" % time.time())
class SleepHandler(tornado.web.RequestHandler):
@unblock
def get(self, n):
time.sleep(float(n))
return "Awake! %s" % time.time()
class SleepAsyncHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self, n):
def callback(future):
self.write(future.result())
self.finish()
EXECUTOR.submit(
partial(self.get_, n)
).add_done_callback(
lambda future: tornado.ioloop.IOLoop.instance().add_callback(
partial(callback, future)))
def get_(self, n):
time.sleep(float(n))
return "Awake! %s" % time.time()
application = tornado.web.Application([
(r"/", MainHandler),
(r"/sleep/(\d+)", SleepHandler),
(r"/sleep_async/(\d+)", SleepAsyncHandler),
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
Ceci est une bonne réponse. – Glycerine
- 1. comment gérer le code de blocage dans PeriodicCallback de tornado
- 2. Déploiement de code Tornado
- 3. Exécution @ gen.coroutine synchrone dans Tornado et Flask
- 4. Exécution de la documentation Tornado localement
- 5. Blocage C# Sélection du code
- 6. Exécution du blocage final dans l'ordre $ ErrorActionPreference = "Stop"
- 7. tornado - transfert d'un fichier vers cdn sans blocage
- 8. Blocage/blocage du code C++ concomitant à l'aide d'Intel TBB
- 9. Exécution du code python
- 10. Blocage du blocage de l'application Caching IIS
- 11. blocage dans le code mutex
- 12. Exécution d'un morceau de code sans blocage utilisant un objet COM créé dans le thread principal
- 13. Exécution du code CloudKit dans les tests?
- 14. Exécution du code php dans l'éditeur WYSIWYG
- 15. Exécution du code Python dans Markdown
- 16. Exécution du code après clearInterval
- 17. Exécution du code d'assemblage dans c
- 18. Exécution du code AJAX dans l'objectif C
- 19. python chronométré exécution du code
- 20. Optimise le code Async Tornado. Minimiser le verrouillage du fil
- 21. Exécution d'une tâche d'arrière-plan avec Python et Tornado
- 22. Boîte de dialogue de blocage à partir du code JNI
- 23. Exécution du code Java de l'intérieur Java
- 24. Exécution du code Python de PHP
- 25. Win32: Exécution atomique du bloc de code
- 26. exécution du code C# de fin avant
- 27. Exécution de deux fonctions de blocage à la fois
- 28. erreur self.finish() dans Tornado
- 29. OpenMP - Exécution de code parallèle à l'intérieur du code parallèle
- 30. équivalent de @inlineCallbacks dans Tornado?
Pouvez-vous fournir plus d'informations sur la façon dont vous voulez bloquer la tornade? Parce que vous pouvez toujours faire 'time.sleep (10)' mais je suis sûr que vous voulez faire autre chose ... –
@StevePeak merci, j'ai ajouté un autre paragraphe – abyx
Drôle, j'ai ce même concept dans l'une de mes applications. Voir mon SO ici: http://stackoverflow.com/questions/13961863/tornado-web-http-request-blocks-other-requests-how-to-not-block-other-requests est votre problème lié à cela? De toute façon, j'aimerais vous aider. –