【妙用协程】 – 可持久化的协程能被用来实现工作流
admin
2023-07-31 01:51:01
0

常规版本的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(\'\\n\', \' \')[: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\'d\\x01\\x00V\\x01d\\x02\\x00V}\\x00\\x00|\\x00\\x00r\\x ...]
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不同版本的流程状态,可以在各个阶段里来回切换。

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
项目管理和工程管理的区别 项目管理 项目管理,顾名思义就是专注于开发和完成项目的管理,以实现目标并满足成功标准和项目要求。 工...