Python 如果decorator函数在库中,我可以';不能修改吗?
我正在谷歌应用程序引擎(GAE)上工作。不幸的是,GAE在使用套接字时会不时引发Python 如果decorator函数在库中,我可以';不能修改吗?,python,sockets,google-app-engine,decorator,statsd,Python,Sockets,Google App Engine,Decorator,Statsd,我正在谷歌应用程序引擎(GAE)上工作。不幸的是,GAE在使用套接字时会不时引发ApplicationError:4未知错误。。该错误是一个apiproxy\u错误。ApplicationError statsd客户端已设置为捕获套接字的socket.error,但未捕获套接字在GAE上可能引发的ApplicationError 我专门使用timer,它返回timer的一个实例: Timer的\uuuu调用\uuu方法允许将其用作装饰器,如下所示: from statsd import Sta
ApplicationError:4未知错误。
。该错误是一个apiproxy\u错误。ApplicationError
statsd客户端已设置为捕获套接字的socket.error
,但未捕获套接字在GAE上可能引发的ApplicationError
我专门使用timer
,它返回timer
的一个实例:
Timer
的\uuuu调用\uuu
方法允许将其用作装饰器,如下所示:
from statsd import StatsClient
statsd = StatsClient()
@statsd.timer('myfunc')
def myfunc(a, b):
"""Calculate the most complicated thing a and b can do."""
然后将使用如下方式:
@my_timer_wrapper('stastd_timer_name')
def timed_func():
do_work()
@我的定时器包装器('stastd定时器名称')
def timed_func():
你工作吗
有更好的或更具python风格的方法吗?看起来这是一个“尽可能简单”的例子 新的装饰器在计时器装饰器周围添加了额外的try/except 唯一的问题是接受参数的decorator需要 要定义的嵌套函数的两个级别,几乎总是使它们 看起来很复杂,即使它们不是:
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。看起来该类可以用作上下文管理器,这将更容易包装在try/except中。您可以直接使用monkey补丁statsd。在appengine_config.py中执行补丁,这样在代码库中只需要执行一次。
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):
...