2

基本上我们可以通过以下方式调用 xmlrpc 处理程序:

import xmlrpclib
s = xmlrpclib.ServerProxy('http://remote_host/rpc/')
print s.system.listmethods()

在龙卷风中,我们可以像这样集成它:

import xmlrpclib
import tornado.web

s = xmlrpclib.ServerProxy('http://remote_host/rpc/')

class MyHandler(tornado.web.RequestHandler):
    def get(self):
        result = s.system.listmethods()

我有以下一些新手问题:

  1. result = s.system.listmethods()阻止龙卷风吗?
  2. 是否有任何非阻塞 xmlrpc 客户端?
  3. 我们怎样才能实现result = yield gen.Task(s.system.listmethods)
4

2 回答 2

3

1.是的,它会阻止龙卷风,因为 xmlrpclib 使用阻塞 python 套接字(原样)

2.不是我知道的,但我会提供一个解决方案,你可以保留 xmlrpclib 但让它异步

3.我的解决方案不使用tornado gen。

好的,所以当你在做网络并且需要编写异步代码时,一个有用的库是 gevent,它是一个非常好的高质量库,我会推荐给每个人。

为什么它好用又好用?

  • 您可以以同步的方式编写异步代码(这样很容易)
  • 你所要做的就是用一条简单的线来做猴子补丁:

    从 gevent 导入猴子;猴子.patch_all()

使用龙卷风时,您需要知道两件事(您可能已经知道):

  • Tornado 仅在充当 HTTPServer 时支持异步视图(异步视图不支持 WSGI)
  • 异步视图需要自行终止响应,您可以使用 self.finish() 或 self.render()(调用 self.finish())

好的,这是一个示例,说明您需要与 tornado 进行必要的 gevent 集成:

# 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()

所以试试这个例子(显然适应你的需要),你应该很高兴。

不需要编写任何额外的代码,gevent 完成了修补 python 套接字的所有工作,因此它们可以异步使用,同时仍然以同步方式编写代码(这是一个真正的好处)。

希望这可以帮助 :)

于 2012-11-11T01:04:02.370 回答
0

我不这么认为。因为 Tornado 有自己的 ioloop,但是 gevent 的 ioloop 是 libevent。所以 gevent 会阻止 Tornado 的 ioloop。

于 2013-09-24T09:13:19.190 回答