【发布时间】:2013-12-13 02:06:00
【问题描述】:
我只是 Tornado 的新手,但不是 Python。
我正在尝试为 CouchDB 编写一个异步客户端(使用 couchdb 包)。
经过 1 天的研究/谷歌搜索,我发现每篇文章都只是简单地使用 HttpAsyncClient 为例,并没有说明 gen.coroutine 工作的原因和方式。 源代码对我来说太复杂了,因为装饰器 HttpAsyncClient 之后的装饰器对我来说是一个不好的例子......
【问题讨论】:
我只是 Tornado 的新手,但不是 Python。
我正在尝试为 CouchDB 编写一个异步客户端(使用 couchdb 包)。
经过 1 天的研究/谷歌搜索,我发现每篇文章都只是简单地使用 HttpAsyncClient 为例,并没有说明 gen.coroutine 工作的原因和方式。 源代码对我来说太复杂了,因为装饰器 HttpAsyncClient 之后的装饰器对我来说是一个不好的例子......
【问题讨论】:
坦率地说,我只是在阅读了源代码之后,我(部分)理解了逻辑
如果你用tornado.gen 装饰了somefunction(),它有点像这样:
yield somefunction() somefunction() 被实际调用tornado.coroutine.gen。它会运行您的代码直到somefunction 中的第一个yield
another_callback()”。 somefunction() 的执行距离,Tornado 维护了一个名为Runner 的特殊对象。它会记住最后一个阻止执行 somefunction() 的 yield 语句,并在执行装饰器 gen 时首次运行。run() 方法返回,装饰器退出,返回它自己的 Futureanother_callback。后者是 Tornado 创建的一个特殊回调,简而言之,它run()s 与在第 3 点运行时相同的 Runner。产生了一个新解决的 Future。Runner 使用.send() 方法将新解析的 Future 值注入到您的somefuncion,这会导致 ait 在您的函数中分配给一个变量(如果有),如下所示:
a = yield some_other_coroutine_for_example_async_client_fetch()
好的,这是一个要点,有很多细节,其中一些我无法理解,尤其是异常处理,但是 HTH
【讨论】:
第一个答案涵盖了很多。我只是想让你知道一个更简单的抽象。 @Gen.coroutine
res = yield foo()
协程思路是异步执行foo(),尤其是当 foo 占用大量 IO 或网络作业时。
yield 可以启动foo() 执行并将控制权转移给调用者。它让 Runner 将此 foo() 任务注册为未来的 obj。然后当foo()成功返回一个结果,这很神奇,Runner会将结果以yield语句执行结果的形式返回(告诉值yield和yield语句执行结果的差异)。
【讨论】: