资讯专栏INFORMATION COLUMN

【generator101】 - stackless的api

philadelphia / 2661人阅读

摘要:如果说相比来说,是一种隐式的协程的话,提供的就更加隐式了。通过调用可以知道这个链表目前的大小。正式因为没有把底层的协程直接控制接口开放,而是强买强卖了一个,所以想要在像那样随心所欲的操纵协程还是颇费一番周折的。

如果说greenlet相比generator来说,是一种隐式的协程的话,stackless python提供的api就更加隐式了。

import stackless

def func(a, b):
    print("2 current: %s" % stackless.getcurrent())
    print("2 main: %s" % stackless.getmain())
    print("2 prev: %s" % stackless.getcurrent().prev)
    print("2 next: %s" % stackless.getcurrent().next)
    print(a)
    stackless.schedule()
    print(b)
    stackless.schedule()
    print("finished")

t = stackless.tasklet()
t.bind(func, ("hello",), {"b": "world"})
print("1 current: %s" % stackless.getcurrent())
print("1 main: %s" % stackless.getmain())
print("1 run count: %s" % stackless.runcount)
t.insert()
print("2 run count: %s" % stackless.runcount)
stackless.schedule()
print("scheduled back to main")
stackless.schedule()
print("2 run count: %s" % stackless.runcount)
stackless.schedule()
print("2 run count: %s" % stackless.runcount)

这段代码的输出是这样的:

1 current: <_stackless.tasklet object at 0x7ffa189b71a0>
1 main: <_stackless.tasklet object at 0x7ffa189b71a0>
1 run count: 1
2 run count: 2
2 current: <_stackless.tasklet object at 0x7ffa18885f30>
2 main: <_stackless.tasklet object at 0x7ffa189b71a0>
2 prev: <_stackless.tasklet object at 0x7ffa189b71a0>
2 next: <_stackless.tasklet object at 0x7ffa189b71a0>
hello
scheduled back to main
world
2 run count: 2
finished
2 run count: 1

与greenlet的代码不同,当一个协程希望切换出去的时候,它无法指定把控制权交给谁。在stackless的api里没有父子协程的概念,无法像generator那样一个yield跳回到父,也无法向greenlet那样greenlet.getcurrent().parent找到父然后跳回去。stackless里就一行

stackless.schedule()

尼玛,这是要往哪里跳?stackless压根没有提供底层的协程给程序员直接使用,它提供的tasklet的api附赠了一个tasklet的scheduler。这个scheduler的调用方式就是stackless.schedule。scheduler把tasklet串成一个链表,每个tasklet都有一个prev一个next,当stackless.schedule的时候就取当前tasklet的next,把下一个tasklet拉起来执行。通过调用stackless.runcount可以知道这个链表目前的大小。可以看到最开始是1,insert之后变成了2,当func执行完了又变回了1。
正式因为stackless没有把底层的协程直接控制接口开放,而是强买强卖了一个scheduler,所以想要在stackless像greenlet那样随心所欲的操纵协程还是颇费一番周折的。最后还是有高人把stackless的高阶接口重新封装成了和greenlet一样的底层接口了。目的就是为了让gevent可以跑在stackless python上(虽然比cPython版本的还慢):
http://syncless.googlecode.com/svn/trunk/syncless/greenlet_using_stackless.py
另外有有一个反过来的版本,在greenlet上封装了一个和stackless python一样的带scheduler的api
http://syncless.googlecode.com/svn/trunk/syncless/greenstackless.py

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37393.html

相关文章

  • generator101】 - pypyapi

    摘要:从到到再到,各家的语法都不太一样。底层的实现是,看名字应该是的意思。然后在这个基础上实现了的和的。的的语法风格也是类似所以从语法上来说就三类这样强制要求的为代表的隐式控制权的为代表强买强卖编码风格的 从generator到greenlet到stackless再到pypy,各家的语法都不太一样。pypy底层的实现是continulet,看名字应该是continuation的意思。然后在这...

    Luosunce 评论0 收藏0
  • generator101】 - generator是一种显式控制协程

    摘要:协程其实就是一个可中途中断,由外部来控制执行进程的函数。这些第三方的选择的共同特点是协程的都是隐式的。这就是显示控制和隐式控制的区别。本文讨论的协程就是这一种,后面会逐渐展开到如何利用这种显示控制的协程来解决阻塞和流程阻塞的问题。 Python官方的实现里,协程只有generator这一招。协程其实就是一个可中途中断,由外部来控制执行进程的函数。除了官方的generator,还有很多第...

    894974231 评论0 收藏0
  • 【协程原理】 - 为什么greenlet状态无法被保存

    摘要:特别是最火的协程框架也无法保存状态,让人非常惋惜。但是因为栈的本身无法持久化,所以也就无法持久化。其难度在于,假设整个要持久化的调用栈全部都是内的,比如纯的。采取的是暴力地把整个栈区域拷贝到上的方式来保存其状态。 python主流的协程实现有五种: cPython的generator cPython的greenlet cPython的fibers stackless python ...

    verano 评论0 收藏0
  • [译] PEP 255--简单生成器

    摘要:第四种选择是在不同的线程中运行生产者和消费者。包含语句的函数被称为生成器函数。然后引发一个异常,表明迭代器已经耗尽。换句话说,未捕获的异常终结了生成器的使用寿命。 showImg(https://segmentfault.com/img/bVbntUq?w=4272&h=2848);我正打算写写 Python 的生成器,然而查资料时发现,引入生成器的 PEP 没人翻译过,因此就花了点时...

    894974231 评论0 收藏0
  • [译] PEP 255--简单生成器

    摘要:第四种选择是在不同的线程中运行生产者和消费者。包含语句的函数被称为生成器函数。然后引发一个异常,表明迭代器已经耗尽。换句话说,未捕获的异常终结了生成器的使用寿命。 showImg(https://segmentfault.com/img/bVbntUq?w=4272&h=2848);我正打算写写 Python 的生成器,然而查资料时发现,引入生成器的 PEP 没人翻译过,因此就花了点时...

    gaosboy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<