Zasadniczo możemy wywołać funkcje obsługi xmlrpc w następujący sposób:
import xmlrpclib
s = xmlrpclib.ServerProxy("http://remote_host/rpc/")
print s.system.listmethods()
W tornado możemy zintegrować to w ten sposób:
import xmlrpclib
import tornado.web
s = xmlrpclib.ServerProxy("http://remote_host/rpc/")
class MyHandler(tornado.web.RequestHandler):
def get(self):
result = s.system.listmethods()
Mam następujące pytania: nowicjusz
- Będzie
result = s.system.listmethods()
blokowe tornado? - Czy są jakieś niezablokowane klienty xmlrpc?
- Jak możemy to osiągnąć
result = yield gen.Task(s.system.listmethods)
?
Odpowiedzi:
3 dla odpowiedzi № 11. Tak, zablokuje tornado, ponieważ xmlrpclib używa blokujących gniazd Pythona (tak jak jest)
2.Nie wiem o tym, ale udostępnię rozwiązanie, w którym możesz przechowywać xmlrpclib, ale asynchronicznie
3. Moje rozwiązanie nie używa genów tornada.
Ok, więc jedną przydatną biblioteką, którą należy mieć na uwadze, gdy tworzysz sieć i potrzebujesz pisać kod asynchroniczny, jest gevent, to naprawdę dobra biblioteka wysokiej jakości, którą polecam wszystkim.
Dlaczego jest dobry i łatwy w użyciu?
- Możesz pisać kod asynchroniczny w sposób synchroniczny (dzięki czemu jest to łatwe)
Wszystko, co musisz zrobić, to zrobić łatkę małpy za pomocą jednej prostej linii:
od gevent import monkey; monkey.patch_all ()
Używając tornada musisz znać dwie rzeczy (które już wiesz):
- Tornado obsługuje tylko widoki asynchroniczne podczas działania jako HTTPServer (WSGI nie jest obsługiwane dla widoków asynchronicznych)
- Widoki asynchroniczne muszą same kończyć odpowiedzi, używając self.finish () lub self.render () (który wywołuje self.finish ())
Ok, oto przykład ilustrujący, czego potrzebujesz przy niezbędnej integracji gevent z tornadem:
# Python immports
import functools
# Tornado imports
import tornado.ioloop
import tornado.web
import tornado.httpserver
# XMLRpc imports
import xmlrpclib
# Asynchronous gevent decorator
def gasync(func):
@tornado.web.asynchronous
@functools.wraps(func)
def f(self, *args, **kwargs):
return gevent.spawn(func, self, *args, **kwargs)
return f
# Our XML RPC service
xml_service = xmlrpclib.ServerProxy("http://remote_host/rpc/")
class MyHandler(tornado.web.RequestHandler):
@gasync
def get(self):
# This doesn"t block tornado thanks to gevent
# Which patches all of xmlrpclib"s socket calls
# So they no longer are blocking
result = xml_service.system.listmethods()
# Do something here
# Write response to client
self.write("hello")
self.finish()
# Our URL Mappings
handlers = [
(r"/", MyHandler),
]
def main():
# Setup app and HTTP server
application = tornado.web.Application(handlers)
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(8000)
# Start ioloop
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
Więc spróbuj tego przykładu (oczywiście dostosuj go do swoich potrzeb) i powinieneś być dobry.
Nie trzeba pisać żadnego dodatkowego kodu, gevent wykonuje całą pracę polegającą na łataniu gniazd pythona, aby mogły być używane asynchronicznie, a jednocześnie pisać kod w synchroniczny sposób (co jest prawdziwym bonusem).
Mam nadzieję że to pomoże :)
0 dla odpowiedzi nr 2
Nie sądzę. Ponieważ Tornado ma swój własny ioloop, ale ioloop gevent to libevent. Więc gevent zablokuje ioloop Tornado.