此文紧接上文协程和并发课程【部分五~七】。
第八部分:栈引起的问题
Trampolining
当程序涉及协程时,我们不能调用使用了 yield (可以挂起)的子函数。yield 语句只能在最上层挂起协程。例如在以下例子中,foo() 函数并不会因为调用了可以被挂起的 bar() 函数就能够被挂起:
1 | def bar(): |
去除这个限制的方法之一就是无栈 Python。具体的实现技巧叫 Trampolining,中文译名跳床。这中文译名怪怪的,我们还是叫 Tramplining 吧。例如,下边就是利用了该技巧的简单例子:
1 | # trampoline.py |
作者对此还用流程图进行了解释:
改进操作系统
1 | # ------------------------------------------------------------ |
作者解释如下:
改进回显服务器
现在所有的 I/O 操作都是都是子协程了:
1 | # echoserver.py |
非阻塞 I/O
除了上边的做法,我们还可以用非阻塞 I/O 重新封装原生 socket(这也是一些协程库的做法,如 Greenlet):
1 | # sockwrap.py |
这样,回显服务器就可以这样子写了:
1 | # echoserver2.py |
基于 Twisted 回显服务器
下例取自 Twisted 官方例子:
1 | #!/usr/bin/python |
第 9 部分:终言
未来主题
在我们的任务调度器上,我们还可以继续探索:
- 任务间通信
- 对阻塞操作处理(如数据库访问)
- 协程多任务和线程
- 错误处理
生成器
生成器其实远比大家认识的要强大:
- 自定义迭代模式
- 处理流水线和数据流
- 事件处理
- 多任务协作
yield 使用场景
yield 常用使用场景:
- 迭代(数据生产者)
- 接收数据(消费者)
- 陷阱(多任务协作)
终于结束了….