国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【妙用協(xié)程】 - 可resume的異常處理

Jeff / 581人閱讀

摘要:標(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ān)文章

  • 妙用協(xié)程】 - 持久化協(xié)程能被用來實(shí)現(xiàn)工作流

    摘要:常規(guī)版本的的是不可以被持久化保存的。在流程被阻塞的時(shí)候比如需要審批老板不在把協(xié)程持久化成入庫(kù),等流程不再阻塞的時(shí)候把協(xié)程重新從數(shù)據(jù)庫(kù)里拉起來繼續(xù)執(zhí)行。 常規(guī)版本的Python的generator是不可以被持久化保存的。但是stackless和pypy這兩個(gè)修改版本的Python解釋器可以。下面這段代碼演示了如何把一個(gè)執(zhí)行中的函數(shù)持久化保存,然后過段時(shí)間再把函數(shù)從上次執(zhí)行到的地方原樣拉起...

    wpw 評(píng)論0 收藏0
  • Lua5.3學(xué)習(xí)筆記

    摘要:對(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ù)讓 ...

    AWang 評(píng)論0 收藏0
  • [譯]PEP 342--增強(qiáng)型生成器:協(xié)程

    摘要:新語法表達(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...

    Cheng_Gang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<