python协程使用场景_【妙用协程】 - 可持久化的协程能被用来实现工作流

常规版本的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不同版本的流程状态,可以在各个阶段里来回切换。

文章来源:segmentfault,作者:taowen。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:william.shi#ucloud.cn(邮箱中#请改为@)进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

3bd16c71c09c78ecd52251f00b4c6dfa.png

后台-系统设置-扩展变量-手机广告位-内容正文底部

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值