我一直在尝试使用Python 2.7和Tornado 3.2。我一直试图让一个简单的协程示例工作,但没有太多运气:
import tornado.web
from tornado.gen import coroutine
from tornado.httpclient import AsyncHTTPClient
from tornado.gen import Return
class MainHandler(tornado.web.RequestHandler):
# Tried with and without @asynchronous
@tornado.web.asynchronous
def get(self):
data = MainService().get_google_data()
self.write(data)
class MainService:
@coroutine
def get_google_data(self):
response = yield AsyncHTTPClient().fetch("http://www.google.com")
raise Return(value = 'hello')
我希望这会写出“你好'当cURLing URL。相反,我得到:
...
File "/vagrant/venv/lib/python2.7/site-packages/tornado/web.py", line 656, in write
raise TypeError("write() only accepts bytes, unicode, and dict objects")
TypeError: write() only accepts bytes, unicode, and dict objects
显然,正在返回Future,但在未来调用result()
会引发另一个异常:DummyFuture does not support blocking for results
Tornado文档说,为了从协程返回一个值,你会引发一个Return异常。看一下源代码,这似乎确实是预期的。然而,当我运行它时,它似乎无法工作。
感谢对此的任何见解!
答案 0 :(得分:4)
您需要yield
拨打get_google_data()
:
class MainHandler(tornado.web.RequestHandler):
@coroutine
def get(self):
data = yield MainService().get_google_data()
self.write(data)
龙卷风协同程序总是返回Future
。您可以通过调用Future
来等待yield
的结果。如果没有yield
,您最终会立即返回Future
,而无需等待协程完成。除了@coroutine
之外,您还应该使用get
方法上的get_google_data
装饰器。如果你想使用回调而不是协同程序,通常会使用@asynchronous
装饰器。