如何在tornado.wsgi.WSGIContainer中使用异步龙卷风API?

时间:2014-01-30 14:48:56

标签: python asynchronous tornado wsgi wsgidav

我尝试使用应该使用异步操作的自定义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。

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

1 个答案:

答案 0 :(得分:4)

WSGI不支持异步。

通常,对于等待Tornado协程完成的函数,函数本身必须是一个协程并且必须yield协程的结果:

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

但是当然像simple_app这样的WSGI函数不能成为协同程序,因为WSGI不理解协同程序。有关WSGI和异步之间不兼容性的更全面解释在Bottle documentation

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