/ / Python. Tornado. Nieblokujący klient xmlrpc - python, xml-rpc, tornado, xmlrpclib

Pyton. Tornado. Nieblokujący klient xmlrpc - python, xml-rpc, tornado, xmlrpclib

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

  1. Będzie result = s.system.listmethods() blokowe tornado?
  2. Czy są jakieś niezablokowane klienty xmlrpc?
  3. Jak możemy to osiągnąć result = yield gen.Task(s.system.listmethods)?

Odpowiedzi:

3 dla odpowiedzi № 1

1. 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.