【发布时间】:2018-06-21 06:20:30
【问题描述】:
我有一个带有大量静态方法和 Tornado 协程装饰器的类。我想添加另一个装饰器,以捕获异常并将它们写入文件:
# 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 使用了 raise Return(...) 方法,这可能是基于 Exceptions 的,也许它会以某种方式阻止 try-catch 其他装饰器......所以,如何使用我的装饰器来处理带有 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
所以,我只需要指定 Tornado Return。我试图将@gen.coroutine 装饰器添加到silenceit 函数并在其中使用yield,但这会导致Future 对象的Future 对象和其他一些奇怪的不可预测的行为。
【问题讨论】:
标签: python exception tornado decorator