子嘉的博客 子嘉的博客
首页
bic-bic
技术
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

高子嘉

没有比脚更长的路,没有比人更高的山
首页
bic-bic
技术
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • install
  • virtualenv
  • stackless
  • twisted
  • pytesseract
  • django

  • python
子嘉
2022-06-04

stackless

# 1. stackless 的安装和使用

stackless 在 python 库中没有默认包含,可以使用 pip 安装,但由于版本原因可能会安装失败。可以使用 pypy 版本的 python,pypy 默认集成了 stackless 库。 https://www.pypy.org/download.html 其他一些安装使用等,可以参照 github 上的说明 https://github.com/stackless-dev/stackless

stackless 可以理解为一个无栈的任务调度处理,那 stackless 就应该描述成一个无栈调用+协程调度。

# 2. stackless 的 hello world

import stackless

def fun(n):
    print n
    stackless.schedule()
    print n
    stackless.schedule()

stackless.tasklet(fun)(3)
stackless.tasklet(fun)(5)
stackless.run()
## 执行输出
# 3
# 5
# 3
# 5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

stackless 通过调用 run 函数启动,通过调用 tasklet 函数增加一个任务。在 stackless 启动后遇到 schedule 调用时当前任务将转向下一个可调用 tasklet 执行。在 stackless 内部会自动维护一个调度队列,以保证调度的顺序。

# 3. 看一个复杂点的例子

import stackless

channel = stackless.channel()

def producer():
    print "producer started."
    for i in range(5):
        channel.send(i)
    print "producer finished."

def consumer():
    print "consumer start. "
    while True:
        data = channel.receive()
        print "consumer data: " + str(data)
        if data == 4:
            break
    print "consumer finished "


stackless.tasklet(producer)()
stackless.tasklet(consumer)()
stackless.run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

这是一个生产者与消费者的例子,它使用 channel 在不同的 tasklet 间通信。当程序执行到 send 和 receive 时,会向 channel 写入消息,并且执行 schedule 调用。

# 4. 再看一个复杂点的例子

#-*- coding:utf-8 -*-
import stackless
import random
import sys

class hackysacker:
    counter = 0
    def __init__(self,name,circle):
        self.name = name
        self.circle = circle
        circle.append(self)
        self.channel = stackless.channel()

        stackless.tasklet(self.messageLoop)()

    def incrementCounter(self):
        hackysacker.counter += 1
        if hackysacker.counter >= turns: # 当循环到达限制,退出
            while self.circle: # 向每个channel发送 exit
                self.circle.pop().channel.send('exit')

    def messageLoop(self):
        while 1:
            message = self.channel.receive() # 等待消息的到来
            if message == 'exit':
                return
            debugPrint("%s got hackeysack from %s" % (self.name, message.name))
            kickTo = self.circle[random.randint(0,len(self.circle)-1)]
            while kickTo is self:
                kickTo = self.circle[random.randint(0,len(self.circle)-1)]
            debugPrint("%s kicking hackeysack to %s" % (self.name, kickTo.name))
            self.incrementCounter()
            kickTo.channel.send(self) # 向kickTo channel 发送消息,消息参数是self

def debugPrint(x):
    if debug:print x

debug = 5
hackysackers = 5
turns = 1

def runit(hs=5,ts=5,dbg=1):
    global hackysackers,turns,debug
    hackysackers = hs
    turns = ts
    debug = dbg

    hackysacker.counter = 0
    circle = []
    one = hackysacker('1',circle)

    for i in range(hackysackers):
        hackysacker(`i`,circle)

    one.channel.send(one)

    try:
        stackless.run()
    except TaskletExit:
        pass

if __name__ == "__main__":
    runit()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

例子来源于网络,该例中每个 hackysacker 会持有一个 tasklet,并且 hackysacker 对象会监听一个特定的 channel,所有的 tasklet 对象会存储在 circle 列表中,并且每个 tasklet 对象持有 circle 列表的引用。循环调用中,每个 tasklet 会随机选择一个 channel,向其发送消息。分片调度

编辑 (opens new window)
上次更新: 2023/02/24, 10:34:03
virtualenv
twisted

← virtualenv twisted→

最近更新
01
mongodb restore
03-06
02
pytesseract
02-28
03
consul
02-24
更多文章>
Theme by Vdoing | Copyright © 2022-2025 子嘉 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式