进行异步调用时,龙卷风中的"yield"如何工作? [英] How does 'yield' work in tornado when making an asynchronous call?

查看:98
本文介绍了进行异步调用时,龙卷风中的"yield"如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我正在学习 龙卷风简介 ,并且遇到了以下代码:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆