【发布时间】:2014-03-06 09:47:28
【问题描述】:
我知道 Python 中的协程使用 get = yield ret、callee.send()、callee.next()。
但是我在 Tornado 源代码 gen.py 中没有找到上面的东西,例如 call.send()。
如何用简单易懂的方式解释 Tornado 中的协程?没有大图,我只是
无法理解 Tornado 做了什么。
【问题讨论】:
我知道 Python 中的协程使用 get = yield ret、callee.send()、callee.next()。
但是我在 Tornado 源代码 gen.py 中没有找到上面的东西,例如 call.send()。
如何用简单易懂的方式解释 Tornado 中的协程?没有大图,我只是
无法理解 Tornado 做了什么。
【问题讨论】:
gen.py 确实 调用send(),但在Runner.run() 中,而不是在engine() 或coroutine() 中,如您所料。
看来engine() 和coroutine() 基本上是评估包装的函数,看它是否返回一个生成器。如果是这样,它会在结果上调用Runner.run(),这在内部似乎循环了send()。虽然它在做什么并不完全清楚......
【讨论】:
gen.py 打电话给send()。我错过了。它将检查屈服点是否准备好并将结果设置回未来。
send 和 next 函数不是 Tornado 的功能,它们是核心 Python 的一部分。更多详情请参见官方文档的PEP 342和this section。
你可以像这样编写自己的协程而不用龙卷风:
>>> def f():
... x = 0
... while True:
... x = x*2
... x = yield x
...
>>> coro = f()
>>> coro.next() #need to call 'next' once to start the coroutine
0
>>> coro.send(10)
20
>>> coro.send(100)
200
>>> coro.send(1000)
2000
>>>
tornado 提供的东西是一个“事件循环”,它允许你在一个进程中运行一堆协程,以在有阻塞 IO 时实现并发。例如,在从数据库读取数据并将结果流式传输到客户端的 Web 服务器中,每个请求都将在单独的协程中运行,并且 tornado 将通过在点上使用 yield/send/next 来同时处理所有这些协程的执行发生 IO 的地方。
【讨论】:
send() 和next() 做什么,他是在问龙卷风是如何工作的,因为他在gen.py 中看不到send()(尽管它在那里),这很令人困惑,因为Tornado 使用收益分配(例如result = yield gen.Task(my_func))。我带着同样的问题来到这里。