摘要:常規版本的的是不可以被持久化保存的。在流程被阻塞的時候比如需要審批老板不在把協程持久化成入庫,等流程不再阻塞的時候把協程重新從數據庫里拉起來繼續執行。
常規版本的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不同版本的流程狀態,可以在各個階段里來回切換。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/37378.html
摘要:特別是最火的協程框架也無法保存狀態,讓人非常惋惜。但是因為棧的本身無法持久化,所以也就無法持久化。其難度在于,假設整個要持久化的調用棧全部都是內的,比如純的。采取的是暴力地把整個棧區域拷貝到上的方式來保存其狀態。 python主流的協程實現有五種: cPython的generator cPython的greenlet cPython的fibers stackless python ...
摘要:是之后引入的標準庫的,這個包使用事件循環驅動的協程實現并發。沒有能從外部終止線程,因為線程隨時可能被中斷。上一篇并發使用處理并發我們介紹過的,在中,只是調度執行某物的結果。 asyncio asyncio 是Python3.4 之后引入的標準庫的,這個包使用事件循環驅動的協程實現并發。asyncio 包在引入標準庫之前代號 Tulip(郁金香),所以在網上搜索資料時,會經常看到這種花的...
摘要:很長一段時間,我都很天真的認為,特別是以為代表的庫,才是協程的樂土。里是沒法實現協程,更別說實現這樣可以的協程的。咱真的是太井底之蛙了。不完全列表如下還有一個據作者說是最的這些協程庫的實現方式都是類似的,都是通過字節碼生成達到的目的。 很長一段時間,我都很天真的認為python,特別是以gevent為代表的庫,才是協程的樂土。Java里是沒法實現協程,更別說實現stackless py...
摘要:所以與多線程相比,線程的數量越多,協程性能的優勢越明顯。值得一提的是,在此過程中,只有一個線程在執行,因此這與多線程的概念是不一樣的。 真正有知識的人的成長過程,就像麥穗的成長過程:麥穗空的時候,麥子長得很快,麥穗驕傲地高高昂起,但是,麥穗成熟飽滿時,它們開始謙虛,垂下麥芒。 ——蒙田《蒙田隨筆全集》 上篇論述了關于python多線程是否是雞肋的問題,得到了一些網友的認可,當然也有...
閱讀 2269·2021-11-23 09:51
閱讀 5657·2021-09-22 15:39
閱讀 3343·2021-09-02 15:15
閱讀 3494·2019-08-30 15:54
閱讀 2355·2019-08-30 15:53
閱讀 1397·2019-08-30 14:04
閱讀 2446·2019-08-29 18:33
閱讀 2364·2019-08-29 13:08