摘要:常规版本的的是不可以被持久化保存的。在流程被阻塞的时候比如需要审批老板不在把协程持久化成入库,等流程不再阻塞的时候把协程重新从数据库里拉起来继续执行。
常规版本的Python的generator是不可以被持久化保存的。但是stackless和pypy这两个修改版本的Python解释器可以。下面这段代码演示了如何把一个执行中的函数持久化保存,然后过段时间再把函数从上次执行到的地方原样拉起。从效果上来说,有点类似于Vmware虚拟机的snapshot的功能:
import cPickle as pickle def generator_can_be_used_as_workflow(): yield "do something" is_approved = yield "ask boss for permission" if is_approved: yield "do another after approved" else: yield "do another after rejected" workflow = generator_as_workflow_engine() print(workflow.next()) print(workflow.next()) # boss is not available now persisted_workflow = pickle.dumps(workflow) print("persisted workflow is like this: [%s ...]" % persisted_workflow.replace(" ", " ")[:150]) # several hours later, boss come back workflow = pickle.loads(persisted_workflow) print(workflow.send(True)) # I approve
这段代码的输出是
do something ask boss for permission persisted workflow is like this: [cstackless._wrap generator p1 (tRp2 (cstackless._wrap frame p3 (cstackless._wrap code p4 (I0 I1 I1 I99 S"dx01x00Vx01dx02x00V}x00x00|x00x00rx ...] do another after approved
利用这个原理,我们可以把一个需要运行很长时间的流程用协程的方式来实现。在流程被阻塞的时候(比如需要审批老板不在)把协程持久化成string入库,等流程不再阻塞的时候把协程重新从数据库里拉起来继续执行。优点自然是轻量简单随意强大,缺点也是随意强大导致流程状态不可被外部直接解读和操作,也无法实现运行中的流程实例的代码升级。所以,这种工作流用在电子政务,或者办公自动化等强人机交互的领域(需要极高的灵活性)是不合适的。在运维的发布变更这样的场合下,主要是调度系统与系统,机器与机器这样比较固定且相对短暂的流程还是比较方便的。
ps:webwork使用的RIFE,是我所知最早的使用协程的流程引擎
下面是一段演示用pypy的greenlet,控制流程前进和回退的例子:
import greenlet if "__main__" == __name__: root = greenlet.getcurrent() def g(): print("enter g") mystack = "special-g-stack" greenlet.getcurrent().parent.switch() print("leave g") def f(): greenlet_g = greenlet.greenlet(g) greenlet_g.switch() root.switch() print("a") greenlet_g.switch() root.switch() print("b") root.switch() print("c") f_greenlet = greenlet.greenlet(f) f_greenlet.switch() f_greenlet_v1 = pickle.dumps(f_greenlet) print("is greenlet g also pickled? %s" % ("special-g-stack" in f_greenlet_v1)) f_greenlet = pickle.loads(f_greenlet_v1) f_greenlet.switch() f_greenlet_v2 = pickle.dumps(f_greenlet) f_greenlet.switch() f_greenlet_v3 = pickle.dumps(f_greenlet) pickle.loads(f_greenlet_v1).switch() pickle.loads(f_greenlet_v3).switch()
输出是:
enter g is greenlet g also pickled? True a leave g b a leave g c
通过loads不同版本的流程状态,可以在各个阶段里来回切换。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/37378.html
摘要:特别是最火的协程框架也无法保存状态,让人非常惋惜。但是因为栈的本身无法持久化,所以也就无法持久化。其难度在于,假设整个要持久化的调用栈全部都是内的,比如纯的。采取的是暴力地把整个栈区域拷贝到上的方式来保存其状态。 python主流的协程实现有五种: cPython的generator cPython的greenlet cPython的fibers stackless python ...
摘要:是之后引入的标准库的,这个包使用事件循环驱动的协程实现并发。没有能从外部终止线程,因为线程随时可能被中断。上一篇并发使用处理并发我们介绍过的,在中,只是调度执行某物的结果。 asyncio asyncio 是Python3.4 之后引入的标准库的,这个包使用事件循环驱动的协程实现并发。asyncio 包在引入标准库之前代号 Tulip(郁金香),所以在网上搜索资料时,会经常看到这种花的...
摘要:很长一段时间,我都很天真的认为,特别是以为代表的库,才是协程的乐土。里是没法实现协程,更别说实现这样可以的协程的。咱真的是太井底之蛙了。不完全列表如下还有一个据作者说是最的这些协程库的实现方式都是类似的,都是通过字节码生成达到的目的。 很长一段时间,我都很天真的认为python,特别是以gevent为代表的库,才是协程的乐土。Java里是没法实现协程,更别说实现stackless py...
摘要:所以与多线程相比,线程的数量越多,协程性能的优势越明显。值得一提的是,在此过程中,只有一个线程在执行,因此这与多线程的概念是不一样的。 真正有知识的人的成长过程,就像麦穗的成长过程:麦穗空的时候,麦子长得很快,麦穗骄傲地高高昂起,但是,麦穗成熟饱满时,它们开始谦虚,垂下麦芒。 ——蒙田《蒙田随笔全集》 上篇论述了关于python多线程是否是鸡肋的问题,得到了一些网友的认可,当然也有...
阅读 2222·2021-11-23 09:51
阅读 5581·2021-09-22 15:39
阅读 3307·2021-09-02 15:15
阅读 3460·2019-08-30 15:54
阅读 2313·2019-08-30 15:53
阅读 1364·2019-08-30 14:04
阅读 2402·2019-08-29 18:33
阅读 2316·2019-08-29 13:08