当前位置: 首页 > 知识库问答 >
问题:

蟒蛇,龙卷风:gen.coroutine装饰者在另一个装饰者中打破尝试捕捉

赖淇
2023-03-14

我有一个类有很多静态方法与龙卷风协程装饰。我想添加另一个装饰器,捕捉异常并将它们写入文件:

# my decorator
def lifesaver(func):
    def silenceit(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as ex:
            # collect info and format it
            res = ' ... '
            # writelog(res)
            print(res)
            return None

    return silenceit

但是,它不适用于gen.coroutine装饰器:

class SomeClass:

    # This doesn't work!
    # I tried to pass decorators in different orders,
    # but got no result.
    @staticmethod
    @lifesaver
    @gen.coroutine
    @lifesaver
    def dosomething1():
        raise Exception("Test error!")


    # My decorator works well
    # if it is used without gen.coroutine.
    @staticmethod
    @gen.coroutine
    def dosomething2():
        SomeClass.dosomething3()

    @staticmethod
    @lifesaver
    def dosomething3():
        raise Exception("Test error!")

我知道,Tornado使用了提高回报(…)的方法,这可能是基于异常的,也许它会以某种方式阻止其他装饰程序的尝试捕获。。。那么,我如何使用我的装饰器来处理Tornado协同程序的异常呢?

多亏了Martijn Pieters,我的代码得以运行:

def lifesaver(func):
    def silenceit(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except (gen.Return, StopIteration):
            raise
        except Exception as ex:
            # collect info and format it
            res = ' ... '
            # writelog(res)
            print(res)

            raise gen.Return(b"")

    return silenceit

所以,我只需要指定TornadoReturn。我试图将@gen.coroutine装饰器添加到沉默函数中,并在其中使用屈服,但这会导致未来对象的未来对象和其他一些奇怪的不可预测行为。

共有1个答案

夏新翰
2023-03-14

您正在装饰gen.coroutine的输出,因为装饰器是自下而上应用的(因为它们自上而下相互嵌套在一起)。

与其装饰协同程序,不如装饰您的函数,并将gen.coroutine装饰器应用于该结果:

@gen.coroutine
@lifesaver
def dosomething1():
    raise Exception("Test error!")

你的装饰器不能真正处理一个@gen.coroutine的装饰函数产生的输出。Tornado依赖异常来传递结果(因为在Python 2中,生成器不能使用返回来返回结果)。你需要确保你通过龙卷风依赖的例外。您还应该重新包装您的包装函数:

from tornado import gen

def lifesaver(func):
    @gen.coroutine
    def silenceit(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except (gen.Return, StopIteration):
            raise
        except Exception as ex:
            # collect info and format it
            res = ' ... '
            # writelog(res)
            print(res)
            raise gen.Return(b"")

    return silenceit

在异常情况下,引发一个空的返回()对象;根据需要调整它。

帮你自己一个忙,不要使用类,只要把staticmethod函数放在里面就行了。只需将这些功能放在模块的顶层即可。类用于组合方法和共享状态,而不是创建名称空间。使用模块来创建名称空间。

 类似资料:
  • 我有一些测试代码: 运行此代码时,我收到一个错误,显示未定义“inputed_num” 我的问题是:在wrap函数中,func是否可以得到“inputed_num”的闭包? 无论如何,如果没有,我应该如何实现我的目标:初始化一些值,并在主函数中直接使用这个值。 思考。

  • 有时我们不希望某个类天生就非常庞大,一次性包含许多职责。那么我们就可以使用装饰者模式。 装饰者模式可以动态地给某个对象添加一些额外的职责,从而不影响这个类中派生的其他对象。 装饰者模式将一个对象嵌入另一个对象之中,实际上相当于这个对象被另一个对象包装起来,形成一条包装链。 一、不改动原函数的情况下,给该函数添加些额外的功能 1. 保存原引用 window.onload = function() {

  • 装饰者模式可以动态的给指定的类添加一些行为和职责,而不用对原代码进行任何修改。当你需要使用子类的时候,不妨考虑一下装饰者模式,可以在原始类上面封装一层。 在 Swift 里,有两种方式实现装饰者模式:扩展 (Extension) 和委托 (Delegation)。

  • 一、装饰者模式的概念 装饰者模式又名包装(Wrapper)模式。装饰者模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。 装饰者模式动态地将责任附加到对象身上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。 二、装饰者模式的结构 装饰者模式以对客户透明的方式动态地给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰者模式可以在不使用创造更多

  • 委托 装饰者模式的另一种实现方案是委托。在这种机制下,一个对象可以和另一个对象相关联。比如你在用 UITableView ,你必须实现 tableView(_:numberOfRowsInSection:) 这个委托方法。 你不应该指望 UITableView 知道你有多少数据,这是个应用层该解决的问题。所以,数据相关的计算应该通过 UITableView 的委托来解决。这样可以让 UITable

  • 扩展 扩展是一种十分强大的机制,可以让你在不用继承的情况下,给已存在的类、结构体或者枚举类添加一些新的功能。最重要的一点是,你可以在你没有访问权限的情况下扩展已有类。这意味着你甚至可以扩展 Cocoa 的类,比如 UIView 或者 UIImage 。 举个例子,在编译时新加的方法可以像扩展类的正常方法一样执行。这和装饰器模式有点不同,因为扩展不会持有扩展类的对象。