【问题标题】:How to understand Tornado gen.coroutine如何理解 Tornado gen.coroutine
【发布时间】:2013-12-13 02:06:00
【问题描述】:

我只是 Tornado 的新手,但不是 Python。

我正在尝试为 CouchDB 编写一个异步客户端(使用 couchdb 包)。

经过 1 天的研究/谷歌搜索,我发现每篇文章都只是简单地使用 HttpAsyncClient 为例,并没有说明 gen.coroutine 工作的原因和方式。 源代码对我来说太复杂了,因为装饰器 HttpAsyncClient 之后的装饰器对我来说是一个不好的例子......

【问题讨论】:

    标签: python tornado


    【解决方案1】:

    坦率地说,我只是在阅读了源代码之后,我(部分)理解了逻辑

    如果你用tornado.gen 装饰了somefunction(),它有点像这样:

    1. 在声明中yield somefunction() somefunction() 被实际调用
    2. 因为它是一个包装器,所以执行的不是你的代码而是tornado.coroutine.gen。它会运行您的代码直到somefunction 中的第一个yield
    3. 如果产生了 Future(placehodler)(返回装饰器代码!),tornado 说:“好的,当这个未来解决时,为 IOLoop 安排一个任务(IOLoop 回调),以便它调用一些 another_callback()”。
    4. 为了跟踪您的somefunction() 的执行距离,Tornado 维护了一个名为Runner 的特殊对象。它会记住最后一个阻止执行 somefunction()yield 语句,并在执行装饰器 gen 时首次运行。
    5. 在第 3 点之后,Future 被“注册”,这个 Runner 从它的主 run() 方法返回,装饰器退出,返回它自己的 Future
    6. 当第 3 点的 Future 准备就绪时,它会向 IOLoop 添加一个任务,然后调用 another_callback。后者是 Tornado 创建的一个特殊回调,简而言之,它run()s 与在第 3 点运行时相同的 Runner。产生了一个新解决的 Future。
    7. Runner 使用.send() 方法将新解析的 Future 值注入到您的somefuncion,这会导致 ait 在您的函数中分配给一个变量(如果有),如下所示:

      a = yield some_other_coroutine_for_example_async_client_fetch()
      

    好的,这是一个要点,有很多细节,其中一些我无法理解,尤其是异常处理,但是 HTH

    【讨论】:

    • 是的,异常处理是一个非常有趣的部分。
    【解决方案2】:

    第一个答案涵盖了很多。我只是想让你知道一个更简单的抽象。 @Gen.coroutine

    res = yield foo()
    

    协程思路是异步执行foo(),尤其是当 foo 占用大量 IO 或网络作业时。 yield 可以启动foo() 执行并将控制权转移给调用者。它让 Runner 将此 foo() 任务注册为未来的 obj。然后当foo()成功返回一个结果,这很神奇,Runner会将结果以yield语句执行结果的形式返回(告诉值yield和yield语句执行结果的差异)。

    【讨论】:

      猜你喜欢
      • 2016-10-03
      • 1970-01-01
      • 2013-09-22
      • 2014-12-13
      • 2016-08-09
      • 2013-08-24
      • 1970-01-01
      • 2017-08-05
      • 2015-02-08
      相关资源
      最近更新 更多