摘要:標(biāo)準(zhǔn)的異常處理是這樣的這段代碼會(huì)打印出而不會(huì)打印出,因?yàn)楫惓?huì)中斷當(dāng)前流程,跳轉(zhuǎn)到部分去繼續(xù)執(zhí)行。這種行為類似里的。如何實(shí)現(xiàn)的其實(shí)原理上很簡(jiǎn)單。的時(shí)候把當(dāng)前協(xié)程的狀態(tài)保存起來,如果決定要,就把協(xié)程的時(shí)刻的狀態(tài)重新恢復(fù)然后從那個(gè)點(diǎn)繼續(xù)執(zhí)行。
標(biāo)準(zhǔn)的異常處理是這樣的
try: print("hello") raise Exception() print("!!!") except: print("world") print("???")
這段代碼會(huì)打印出???而不會(huì)打印出!!!,因?yàn)楫惓?huì)中斷當(dāng)前流程,跳轉(zhuǎn)到except部分去繼續(xù)執(zhí)行。但是有的時(shí)候我們希望的這樣的行為:
try: print("hello") print(Scheduler.interrupt()) print("!!!") except ProcessInterrupt as pi: pi.resume("world") print("???")
這段代碼打印出!!!而不是???,因?yàn)閞esume的時(shí)候把執(zhí)行重新跳轉(zhuǎn)回interrupt的地方了。這種行為類似vba里的on error resume next(https://msdn.microsoft.com/en-us/library/5hsw66as.aspx)。
如何實(shí)現(xiàn)的?其實(shí)原理上很簡(jiǎn)單。interrupt的時(shí)候把當(dāng)前協(xié)程的狀態(tài)保存起來(pickle.dumps),如果決定要resume,就把協(xié)程interrupt的時(shí)刻的狀態(tài)重新恢復(fù)(pickle.loads)然后從那個(gè)點(diǎn)繼續(xù)執(zhí)行。
完整的代碼(需要pypy或者stackless python):
import greenlet import cPickle as pickle import traceback import threading import functools class ProcessInterrupt(Exception): def __init__(self, interruption_point, pi_args): self.interruption_point = interruption_point self.stacktrace = traceback.extract_stack() self.pi_args = pi_args def resume(self, resume_with=None): Scheduler.resume(self.interruption_point, resume_with) def __repr__(self): return ">>>ProcessInterrupt>>>%s" % repr(self.stacktrace) def __str__(self): return repr(self) def __unicode__(self): return repr(self) class Scheduler(object): current = threading.local() def __init__(self): if getattr(self.current, "instance", None): raise Exception("can not have two scheduler in one thread") self.scheduler_greenlet = greenlet.getcurrent() self.current.instance = self def __call__(self, action, action_args): next = action, action_args while next: action, action_args = next if "init" == action: next = action_args["init_greenlet"].switch() elif "interrupt" == action: interruption_point = pickle.dumps(action_args["switched_from"]) should_resume, resume_with = False, None next = action_args["switched_from"].switch( should_resume, resume_with, interruption_point) elif "resume" == action: should_resume, resume_with, interruption_point = True, action_args["resume_with"], action_args[ "interruption_point"] next = pickle.loads(action_args["interruption_point"]).switch( should_resume, resume_with, interruption_point) else: raise NotImplementedError("unknown action: %s" % action) @classmethod def start(cls, init_func, *args, **kwargs): scheduler = Scheduler() init_greenlet = greenlet.greenlet(functools.partial(init_func, *args, **kwargs)) scheduler("init", { "init_greenlet": init_greenlet, }) @classmethod def interrupt(cls, pi_args=None): should_resume, resume_with, interruption_point = cls.switch_to_scheduler("interrupt", { "switched_from": greenlet.getcurrent() }) if should_resume: return resume_with else: pi = ProcessInterrupt(interruption_point, pi_args) raise pi @classmethod def resume(cls, interruption_point, resume_with=None): cls.switch_to_scheduler("resume", { "interruption_point": interruption_point, "resume_with": resume_with }) @classmethod def switch_to_scheduler(cls, *args, **kwargs): return cls.current.instance.scheduler_greenlet.switch(*args, **kwargs) if "__main__" == __name__: def init(): try: print("hello") print(Scheduler.interrupt()) print("!!!") except ProcessInterrupt as pi: pi.resume("world") print("???") try: print("hello") raise Exception() print("!!!") except: print("world") print("???") Scheduler.start(init)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/37582.html
摘要:常規(guī)版本的的是不可以被持久化保存的。在流程被阻塞的時(shí)候比如需要審批老板不在把協(xié)程持久化成入庫(kù),等流程不再阻塞的時(shí)候把協(xié)程重新從數(shù)據(jù)庫(kù)里拉起來繼續(xù)執(zhí)行。 常規(guī)版本的Python的generator是不可以被持久化保存的。但是stackless和pypy這兩個(gè)修改版本的Python解釋器可以。下面這段代碼演示了如何把一個(gè)執(zhí)行中的函數(shù)持久化保存,然后過段時(shí)間再把函數(shù)從上次執(zhí)行到的地方原樣拉起...
摘要:對(duì)于正常結(jié)束,將返回,并接上協(xié)程主函數(shù)的返回值。當(dāng)錯(cuò)誤發(fā)生時(shí),將返回與錯(cuò)誤消息。通過調(diào)用使協(xié)程暫停執(zhí)行,讓出執(zhí)行權(quán)。通用形式的通過一個(gè)叫作迭代器的函數(shù)工作。 Lua 是一門強(qiáng)大、輕量的嵌入式腳本語言,可供任何需要的程序使用。Lua 沒有 main 程序的概念: 它只能 嵌入 一個(gè)宿主程序中工作.宿主程序可以調(diào)用函數(shù)執(zhí)行一小段 Lua 代碼,可以讀寫 Lua 變量,可以注冊(cè) C 函數(shù)讓 ...
摘要:新語法表達(dá)式語句可以被用在賦值表達(dá)式的右側(cè)在這種情況下,它就是表達(dá)式。表達(dá)式必須始終用括號(hào)括起來,除非它是作為頂級(jí)表達(dá)式而出現(xiàn)在賦值表達(dá)式的右側(cè)。 showImg(https://segmentfault.com/img/bVbnQsb?w=4344&h=2418);PEP原文 : https://www.python.org/dev/pe... PEP標(biāo)題: Coroutines v...
閱讀 645·2023-04-26 02:08
閱讀 2667·2021-11-18 10:02
閱讀 3472·2021-11-11 16:55
閱讀 2354·2021-08-17 10:13
閱讀 2913·2019-08-30 15:53
閱讀 695·2019-08-30 15:44
閱讀 2560·2019-08-30 11:10
閱讀 1766·2019-08-29 16:57