StacklessPython简要笔记
StacklessPython简要笔记
| 作者: | gashero |
|---|
1 微进程tasklet
stackless的基本构成单元,一种可调度对象。
1.1 建立微进程对象
示例:
import stackless
def print_x(x):
print x
stackless.tasklet(print_x)('one')
stackless.run()
微进程建立后并不运行,直到调用 stackless.run() 才开始运行。
1.2 调度
微进程执行的函数内部可以调用 stackless.schedule() 来暂停当前微进程而把执行权交给执行队列的下一个微进程。
这也是在stackless中实现协程的基本方式。
1.3 轻量级进程
class HackySacker:
def __init__(self):
#todo...
self.channel=stackless.channel()
stackless.tasklet(self.messageLoop)()
def messageLoop(self):
while True:
message=self.channel.receive()
if message=='exit':
return
#todo...
stackless.schedule() #这里注意要调度一下
执行速度比线程的更快,而且可以允许10000个微进程而不死掉。
2 通道channel
用于微进程之间传递信息和控制微进程的运行流程。可以替代传统线程程序中的Queue模块的互斥队列。
2.1 交换信息
示例:
import stackless
channel=stackless.channel()
def recv_tasklet():
msg=channel.receive()
print msg
def send_tasklet():
channel.send('hello')
调用 channel.receive() 时会阻塞当前微进程,等待消息到来。调用 channel.send() 时也会阻塞,直到有微进程读取了消息。
2.2 任务分发
如果一个入口微进程将消息源源不断的发送到通道,而多个工作者微进程等待接受消息,那么每个消息只能被一个微进程所接受,而不是被所有接受。
2.3 事件管理器
使用channel实现的一个基类,用于事件的等待与处理。
class EventHandler:
def __init__(self,*outputs):
if outputs==None:
self.outputs=[]
else:
self.outputs=list(outputs)
self.channel=stackless.channel()
stackless.tasklet(self.listen)()
def listen(self):
while True:
val=self.channel.receive()
self.processMessage(val)
for output in self.outputs:
self.notify(output)
def processMessage(self,val):
pass
def notify(self,output):
pass
def registerOutput(self,output):
self.outputs.append(output)
def __call__(self,val):
self.channel.send(val)
功能:
- 通过 listen 方法,持续的监听通道上传来的消息。
- 通过 processMessage 处理收到的消息。
- 通过 notify 方法将收到的结果发送到输出端。
- registerOutput 可以添加新加的输出端。
- __call__ 可以方便的用对象后加参数来给它发消息。
3 协程coroutine
使用通道实现,两个函数都在循环中等待对方发来的消息。
3.1 乒乓球的例子
import stackless
ping_channel=stackless.channel()
pong_channel=stackless.channel()
def ping():
while ping_channel.receive(): #在此阻塞
#todo...
pong_channel.send('from ping')
def pong():
while pong_channle.receive():
#todo...
ping_channel.send('from pong')
stackless.tasklet(ping)()
stackless.tasklet(pong)()
stackless.tasklet(ping_channel.send)('startup') #启动循环的微进程
stackless.run()