或许你可以想到我正在尝试做的另一种解决方案。基本上我有一个带有一堆函数的类,我想在try / except块中包装来拦截 KeyboardInterrupt 错误,因为我有一个整洁地清理我的每个函数的函数。
我没有在每个函数中放置巨大的try catch块,而是认为我可以创建一个装饰器来做到这一点,但我遇到了一些问题。到目前为止,我有类似的东西
class MyClass:
def catch_interrupt(self, func):
def catcher():
try:
func()
except KeyboardInterrupt:
self.End()
return catcher
@catch_interrupt
def my_func(self):
# Start a long process that might need to be interrupted
def End(self):
# Cleans up things
sys.exit()
运行此问题时,我收到错误
TypeError: catch_interrupt() takes exactly 2 arguments (1 given)
这甚至可能吗?有没有更好的方法或者我应该在每个函数内部放置try / except块?
答案 0 :(得分:2)
确实可以在类中创建一个装饰器,但是你的实现是错误的:
首先,catch_interrupt()
无法取self
。
@catch_interrupt
def my_func(self):
# Start a long process that might need to be interrupted
相当于
def my_func(self):
# Start a long process that might need to be interrupted
my_func = catch_interrupt(my_func)
显然这不允许self
。
其次,从装饰器返回的内部包装函数至少需要将self
作为参数并将其传递给func
,因为您将要装饰的函数期望{{1作为他们的第一个参数。
您可能还想调用内部装饰器self
来暗示它是用于内部使用的。这不会阻止任何人调用它,但是如果在类的实例上调用行为将是不正确的,这是很好的做法(例如_catch_interrupt
将尝试装饰MyClass().catch_interrupt()
实例本身,你可能不想要。)
然而,我的建议是实现context manager而是让它执行清理。对于你只是封闭一组语句的情况,这就更Pythonic了,如果你正确实现它,你实际上也可以将它用作装饰器。
答案 1 :(得分:0)
我不确定你是否可以在你提议的性质中使用类中的装饰器。我认为这对于装饰者本身的目的是违反直觉的(黑客,可以这么说)。
try-except块有什么问题?您已将所有清理代码放在一个函数中,因此遵守DRY原则。装饰器和/或包装器只会通过修复try-except语句包装整个函数来限制错误处理的灵活性,而不会提供任何真正的额外好处。