进行异步调用时,龙卷风中的"yield"如何工作? [英] How does 'yield' work in tornado when making an asynchronous call?
问题描述
最近,我正在学习 龙卷风简介 ,并且遇到了以下代码:
Recently, I was learning Introduction to Tornado, and I came across the following code:
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中尝试了以下代码:
I used to learn that yield
is the key word turning a common function into a generator, and when it used in the form other = yield foo
means, "yield foo and, when a value is sent to me, set other to that value." So I tried the following code in 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':
Now I printed the global varialbe result
, and it still referred to string 'init':
In [5]: print result
init
然后我调用了send()
方法,并向yield
发送了一个新字符串:
Then I called the send()
method, and sent a new string to 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
已被更改:
As expected, a StopIteration
was raised and output the string 'end test...', but now the global variable result
has been changed:
In [7]: print result
new message
显然,当我们调用send()
方法时,yield
语句接受了字符串,并将新的字符串分配给变量result.
Apperantly, the yield
statement accepted the string when we called the send()
method, and assigned the new string to the variable result.
我的问题是:
根据此逻辑,返回顶部显示的代码,
Back to the code showed on the top, according to this logic,
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()
方法.我对此非常困惑,徒劳地搜索了谷歌.
when method client.fetch
returned, a Task
instance would be created and yield
to the caller, but the variable response
on the left will recieve nothing because no send()
method has been excuted. I got quite confused about this, and googled in vain.
非常感谢您的解释!
推荐答案
您已经已经了解Tornado如何使用生成器来处理异步调用.
You are already understanding how Tornado uses generators to handle async calls.
我在这里假设client
是 tornado.httpclient.AsyncHTTPClient()
;它的fetch()
方法具有回调函数.
I'm assuming here that client
is an instance of tornado.httpclient.AsyncHTTPClient()
; it's fetch()
method takes a callback function.
tornado.gen.Task
对象只需要一个对client.fetch
方法的引用;您当时还没有称呼它.您正在使用该方法引用和一个参数构造一个Task()
实例,然后产生该实例.
The tornado.gen.Task
object only takes a reference to the client.fetch
method; you are not calling it at that point. You are constructing a Task()
instance with that method reference and an argument, then yielding that.
Tornado将运行该Task
; Task
会依次使用提供的参数加上回调函数调用client.fetch()
.然后client.fetch()
异步运行,并调用回调.然后将传递给回调的所有内容记录为Task
结果.
Tornado will then run that Task
; the Task
will in turn call client.fetch()
with the argument provided, plus a callback function. The client.fetch()
then runs asynchronously, and calls the callback. Whatever is then passed to the callback is then recorded as the Task
result.
然后将结果与send()
发送到您的IndexHandler.get()
生成器,从yield Task()
表达式返回并分配给response
.
That result is then sent to your IndexHandler.get()
generator with send()
, returned from the yield Task()
expression and assigned to response
.
换句话说,龙卷风确实在这里使用.send()
,并且 分配给response
.
In other words, Tornado does use .send()
here and something is assigned to response
.
这篇关于进行异步调用时,龙卷风中的"yield"如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!