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

如果decorator函数位于我无法修改的库中,我应该如何捕获可能引发的decorator函数中的异常?

东郭腾
2023-03-14

我正在谷歌应用程序引擎(GAE)上使用python statsd库。不幸的是,GAE在使用套接字时会不时引发ApplicationError:4未知错误。。该错误是一个apiproxy\u错误。ApplicationError

statsd客户端已经设置为捕获socket.error,但不是套接字可以在GAE上引发的Application ationError

我专门使用timer,它返回timer的一个实例:https://github.com/jsocol/pystatsd/blob/master/statsd/client.py#L13

Timer__call__方法允许将其用作装饰器,如下所示:

from statsd import StatsClient

statsd = StatsClient()

@statsd.timer('myfunc')
def myfunc(a, b):
    """Calculate the most complicated thing a and b can do."""

我没有修改计时器的简单能力。\uu调用\uu方法本身来捕获ApplicationError

我应该如何编写一个包装器或附加装饰器,它仍然允许像@my\u timer\u wrapper('statsd\u timer\u name')这样干净的装饰,但它会捕获包装/装饰timer方法中可能发生的附加异常?

这是我的代码库中的一个基础模块,它将被用于很多地方(无论我们想在什么地方使用时间)。因此,尽管这个答案可能有效,但我确实希望避免强制在代码库中使用@statclient.timer的所有用法都在try except块中定义。

我正在考虑做如下事情:

def my_timer_wrapper(wrapped_func, *args, **kwargs):
  @functools.wraps(wrapped_func)
  class Wat(object):
    def __call__(self, *args, **kwargs):
      timer_instance = stats_client.timer(*args, **kwargs)
      try:
        return timer_instance.__call__(wrapped_func)(*args, **kwargs)
      except Exception:
        logger.warning("Caught exception", exc_info=True)
        def foo():
          pass
        return foo

  return Wat()

然后将使用如下方式:

@my_timer_wrapper('stastd_timer_name')
def timed_func():
  do_work()

有更好或更像蟒蛇的方法吗?

共有1个答案

计阳泽
2023-03-14

这似乎是一个“尽可能简单”的新装饰器在计时器装饰器周围添加额外的try/except的情况。

唯一的问题是,使用需要定义2级嵌套函数的参数的装饰器几乎总是使它们看起来很复杂,即使它们不是:

from functools import wraps

def  shielded_timer(statsd, 
                    exceptions=(apiproxy_errors.ApplicationError),
                    name=None):

    def decorator(func):
        timer_decorator = statsd.timer(name or func.__name__)
        new_func = timer_decorator(func)
        @wraps(func)
        def wrapper(*args, **kw):
            try:
                return new_func(*args, **kw)
            except BaseException as error:
                if isinstance (error, exceptions):
                    # Expected error (ApplicationError by default) ocurred
                    pass
                else:
                    raise
        return wrapper
    return decorator



#####################
statsd = StatsClient()
@shielded_timer(statsd)
def my_func(a,b):
    ...

正如您所看到的,甚至可以很容易地包含额外的细节——在本例中,我已经在装饰时配置了想要的异常,并且可以选择在调用statsd.timer时自动使用装饰函数的名称。

 类似资料:
  • 问题内容: 我正在学习使用装饰器模式,但遇到一个我认为很简单但似乎找不到答案的问题。假设我有一个抽象的饮料类。然后,让我们说一下扩展饮料的一些具体组成部分:美式咖啡,浓缩咖啡,拿铁咖啡等。还有扩展饮料的抽象调味品类。然后,调味品类有多个子类:牛奶,糖,大豆,鞭子。每个调味品子类都有一个cost和getdescription()方法,分别从Beverage和Condiments继承。我的问题是,如何

  • 我正在学习使用decorator模式,我遇到了一个问题,我认为这个问题很简单,但我似乎找不到答案。假设我有一个饮料课是抽象的。然后让我们假设我有几个具体的成分延伸饮料:美式咖啡,浓缩咖啡,拿铁等等,还有一个抽象的调味品类延伸饮料。调味品类又有多个子类:牛奶、糖、大豆、鞭。每个调味品子类都有一个cost和getdescription()方法,分别继承自Beverage和addinments。我的问题

  • 我正在尝试创建一个可以传递其他函数的函数,它将捕获任何错误,但只返回函数的返回值。以下是我尝试过的: 我希望意图相对明确;我希望能够接收任何类型的函数,并返回其返回值(只要在出错的情况下隐式可转换为该值)。然而,当我试图编译上述代码时,我得到了这些类型的错误; 掠夺。cpp:10:78:错误:应在“…”之前使用主表达式令牌静态自动处理呼叫(const F 很明显,我没有正确地使用可变模板。。。有什

  • 问题内容: 我正在为项目编写自定义日志记录系统。如果一个函数抛出异常,我想记录它的局部变量。是否可以从捕获异常的except块中访问提升函数的局部变量?例如: 问题答案: 如果您知道异常处理代码将需要使用该值,那么通常将其传递给异常是一种更干净的设计。但是,如果要编写调试器或类似的东西,则需要在不事先知道变量的情况下访问变量,则 可以 在引发异常的上下文中访问任意变量: 模块文档中介绍了该功能的功

  • 问题内容: 我有一个可执行文件和一个动态库(.so)。该库会导出一些符号,并且可执行文件会成功调用它。但是我想使库调用可执行文件的功能成为可能。我试图在可执行文件中执行以下操作: 和这个在图书馆: 但是当我调用可执行文件(以加载库)时,它返回error 。我该如何解决? 问题答案: 在Linux / ELF中,您可以将选项传递给链接器(在编译器驱动程序上),以便将可执行文件中的符号导出到共享库中。

  • 问题内容: 我想出于调试目的,打印出与python方法中执行的每一行有关的内容。 例如,如果该行中有一些赋值,我想打印为该变量分配的值,如果有一个函数调用,我想打印出该函数返回的值,等等。 因此,例如,如果我要使用装饰器,则将其应用于函数/方法,例如: 调用功能测试时,应打印以下内容: 有什么办法可以做到这一点?更重要的是,我想知道我是否可以编写可以逐行通过其他代码的代码,检查它是哪种类型的指令,