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

資訊專欄INFORMATION COLUMN

【妙用協程】 - 可resume的異常處理

Jeff / 576人閱讀

摘要:標準的異常處理是這樣的這段代碼會打印出而不會打印出,因為異常會中斷當前流程,跳轉到部分去繼續執行。這種行為類似里的。如何實現的其實原理上很簡單。的時候把當前協程的狀態保存起來,如果決定要,就把協程的時刻的狀態重新恢復然后從那個點繼續執行。

標準的異常處理是這樣的

try:
    print("hello")
    raise Exception()
    print("!!!")
except:
    print("world")
    print("???")

這段代碼會打印出???而不會打印出!!!,因為異常會中斷當前流程,跳轉到except部分去繼續執行。但是有的時候我們希望的這樣的行為:

try:
    print("hello")
    print(Scheduler.interrupt())
    print("!!!")
except ProcessInterrupt as pi:
    pi.resume("world")
    print("???")

這段代碼打印出!!!而不是???,因為resume的時候把執行重新跳轉回interrupt的地方了。這種行為類似vba里的on error resume next(https://msdn.microsoft.com/en-us/library/5hsw66as.aspx)。

如何實現的?其實原理上很簡單。interrupt的時候把當前協程的狀態保存起來(pickle.dumps),如果決定要resume,就把協程interrupt的時刻的狀態重新恢復(pickle.loads)然后從那個點繼續執行。

完整的代碼(需要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)

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/37582.html

相關文章

  • 妙用協程】 - 持久化協程能被用來實現工作流

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

    wpw 評論0 收藏0
  • Lua5.3學習筆記

    摘要:對于正常結束,將返回,并接上協程主函數的返回值。當錯誤發生時,將返回與錯誤消息。通過調用使協程暫停執行,讓出執行權。通用形式的通過一個叫作迭代器的函數工作。 Lua 是一門強大、輕量的嵌入式腳本語言,可供任何需要的程序使用。Lua 沒有 main 程序的概念: 它只能 嵌入 一個宿主程序中工作.宿主程序可以調用函數執行一小段 Lua 代碼,可以讀寫 Lua 變量,可以注冊 C 函數讓 ...

    AWang 評論0 收藏0
  • [譯]PEP 342--增強型生成器:協程

    摘要:新語法表達式語句可以被用在賦值表達式的右側在這種情況下,它就是表達式。表達式必須始終用括號括起來,除非它是作為頂級表達式而出現在賦值表達式的右側。 showImg(https://segmentfault.com/img/bVbnQsb?w=4344&h=2418);PEP原文 : https://www.python.org/dev/pe... PEP標題: Coroutines v...

    Cheng_Gang 評論0 收藏0

發表評論

0條評論

Jeff

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<