【问题标题】:How to use async tornado API inside tornado.wsgi.WSGIContainer?如何在 tornado.wsgi.WSGIContainer 中使用异步龙卷风 API?
【发布时间】:2014-01-30 14:48:56
【问题描述】:

我尝试使用应该与异步操作一起使用的自定义 WSGIContainer:

from tornado import httpserver, httpclient, ioloop, wsgi, gen

@gen.coroutine
def try_to_download():
    response = yield httpclient.AsyncHTTPClient().fetch("http://www.stackoverflow.com/")
    raise gen.Return(response.body)


def simple_app(environ, start_response):
    res = try_to_download()

    print 'done: ', res.done()
    print 'exec_info: ', res.exc_info()

    status = "200 OK"
    response_headers = [("Content-type", "text/html")]
    start_response(status, response_headers)
    return ['hello world']


container = wsgi.WSGIContainer(simple_app)
http_server = httpserver.HTTPServer(container)
http_server.listen(8888)
ioloop.IOLoop.instance().start()

但这行不通。似乎应用程序不等待 try_to_download 函数结果。下面的代码也不起作用:

from tornado import httpserver, httpclient, ioloop, wsgi, gen


@gen.coroutine
def try_to_download():
    yield gen.Task(httpclient.AsyncHTTPClient().fetch, "http://www.stackoverflow.com/")


def simple_app(environ, start_response):

    res = try_to_download()
    print 'done: ', res.done()
    print 'exec_info: ', res.exc_info()

    status = "200 OK"
    response_headers = [("Content-type", "text/html")]
    start_response(status, response_headers)
    return ['hello world']


container = wsgi.WSGIContainer(simple_app)
http_server = httpserver.HTTPServer(container)
http_server.listen(8888)
ioloop.IOLoop.instance().start()

您知道为什么它不起作用吗?我使用的 Python 版本是 2.7。

附:你可能会问我为什么不想使用原生 tornado.web.RequestHandler。主要原因是我有自定义 python 库(WsgiDAV),它可以生成 WSGI 接口并允许编写自定义适配器,我可以使它们异步。

【问题讨论】:

    标签: python asynchronous tornado wsgi wsgidav


    【解决方案1】:

    WSGI 不适用于异步。

    一般来说,要等待 Tornado 协程完成的函数,函数本身必须是协程并且必须 yield 协程的结果:

    @gen.coroutine
    def caller():
        res = yield try_to_download()
    

    当然,像simple_app 这样的 WSGI 函数不能是协程,因为 WSGI 不理解协程。 Bottle documentation 中对 WSGI 和 async 之间的不兼容有更彻底的解释。

    如果您必须支持 WSGI,请不要使用 Tornado 的 AsyncHTTPClient,而是使用标准的 urllib2 或 PyCurl 之类的同步客户端。如果必须使用 Tornado 的 AsyncHTTPClient,请不要使用 WSGI。

    【讨论】:

    • 感谢您的回答。看来你是对的。但是目前我不知道为什么 WSGIContainer 之类的功能如果不能与 tornado 异步编程 API 一起使用,为什么可以在 tornado 应用程序中使用。所以它会阻塞主应用程序。
    • 只要您使用的 WSGI 应用程序足够快,您不介意阻塞事件循环,您就可以使用 WSGIContainer。当 WSGI 应用程序与 Tornado 应用程序在同一个进程中有一些好处时,它特别有用——例如,我使用 WSGIContainer 将 Dowser 插入到我的 Tornado 应用程序中以检测内存泄漏。
    猜你喜欢
    • 1970-01-01
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多