【发布时间】:2014-11-14 22:46:30
【问题描述】:
最近在学习Tornado简介,偶然发现如下代码:
class IndexHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
@tornado.gen.engine
def get(self):
query = self.get_argument('q')
client = tornado.httpclient.AsyncHTTPClient()
response = yield tornado.gen.Task(client.fetch,
"http://search.twitter.com/search.json?" + \
urllib.urlencode({"q": query, "result_type": "recent", "rpp": 100}))
body = json.loads(response.body)
[...omitted the following code...]
我曾经知道yield是把一个普通函数变成一个生成器的关键词,当它以other = yield foo的形式使用时,意味着“yield foo,当一个值被发送给我时,将 other 设置为该值。” 所以我在 ipython 中尝试了以下代码:
In [1]: result = 'init' #set a global variable
In [2]: def test_yield():
...: global result
...: print 'start test...'
...: result = yield 'foo'
...: print 'end test...'
...:
In [3]: t = test_yield()
In [4]: t.next()
start test...
Out[4]: 'foo' #'foo' has been yield to the caller, and blocked
现在我打印了全局变量result,它仍然引用了字符串'init':
In [5]: print result
init
然后我调用了send()方法,给yield发送了一个新字符串:
In [6]: t.send('new message')
end test...
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
/home/chiyu/<ipython-input-6-b86312ad7d0e> in <module>()
----> 1 t.send('new message')
StopIteration:
正如预期的那样,引发了StopIteration 并输出字符串'end test...',但现在全局变量result 已更改:
In [7]: print result
new message
显然,yield 语句在我们调用send() 方法时接受了该字符串,并将新字符串分配给变量结果。
我的问题是:
回到上面显示的代码,按照这个逻辑,
response = yield tornado.gen.Task(client.fetch,
"http://search.twitter.com/search.json?" + \
urllib.urlencode({"q": query, "result_type": "recent", "rpp": 100}))
当方法client.fetch 返回时,将创建一个Task 实例并将yield 发送给调用者,但左侧的变量response 将不会收到任何信息,因为没有执行send() 方法。我对此感到很困惑,并且徒劳无功。
非常感谢您的解释!
【问题讨论】:
-
client.fetch未被调用;它只是被引用。Task()对象将负责实际调用它。 -
您认为 Tornado 不会在您的生成器上使用
send()的原因是什么? -
这里的
client是什么,是tornado.httpclient.AsyncHTTPClient的实例吗?
标签: python asynchronous generator tornado yield