我正在使用以下模型:
import time
class A:
def do_action_1(self):
print("A: action 1")
def do_action_2(self):
print("A: action 2")
raise Exception
class B:
def __init__(self,A):
self.a = A
self.status = None
def call_action_1(self):
self.a.do_action_1()
def call_action_2(self):
self.a.do_action_2()
a = A()
b = B(a)
while True:
try:
print("call action 1")
b.call_action_1()
print("call action 2")
b.call_action_2()
except Exception as e:
print ("exception catched")
while True:
try:
b.call_action_2()
break
except Exception:
print ("exception catched")
print ("waiting 3s ...")
time.sleep(3)
我需要以某种方式修改b.status
,当从B内部调用的a.do_action_2
引发异常时。
b.call_action_2
在不同的地方被多次调用,因此硬编码try except
不是我想要的,也不是优雅的。我试图使用某种装饰,但我总是失败。看起来我错过了什么。
如果您有任何建议,请告诉我。此外,欢迎任何有关设计的评论。
此致
Ĵ
答案 0 :(得分:0)
我不完全确定我理解你的问题,但我会对它进行一次尝试。
装饰器的一般想法是你想要为你已经喜欢的类添加行为,但由于某种原因不能直接改变。
你基本上想要围绕原始类包装一个新类,并给它额外的行为。
当你这样做时,你想将新的功能推送到新的装饰器中,这样你就不必在其他任何地方改变代码。
在您的示例中,最重要的是状态是B类的一部分,而不是A类。您还希望将所有重试逻辑移动到B类。
看起来像这样:
import time
class A:
def do_action_1(self):
print("A: action 1")
def do_action_2(self):
print("A: action 2")
raise Exception
class B:
def __init__(self,A):
self.a = A
self.status = 'None'
def call_action_1(self):
self.a.do_action_1()
def call_action_2(self):
while self.status != 'Success':
try:
self.a.do_action_2()
self.status = 'Success'
except Exception as e:
self.status = 'Failure'
print("exception caught inside decorator B")
print("> waiting 3s ...")
time.sleep(3)
## some sort of safety maximum attempt should be implemented so you don't get into an infinite loop here.
a = A()
b = B(a)
while True:
try:
print("call action 1")
b.call_action_1()
print("call action 2")
b.call_action_2()
except Exception as e:
print("exception in main")
为了安全起见,您应该为B类实现某种最大尝试次数,以便在X尝试do_action_2()后停止尝试。
答案 1 :(得分:0)
最后使用装饰器完成:
import time
global x
x = 0
def errorDecorator(func):#check if it is called by correct class need be done
def wrapper(self,*args):
try:
return func(self,*args)
except ZeroDivisionError as e:
print ('error catched and processed ')
global x
x = 1 + x
self.status='updated' + str(x)
raise e
return wrapper
class A:
def do_action_1(self):
print("A: action 1")
def do_action_2(self):
print("A: action 2")
1/0
class B:
def __init__(self,A):
self.a = A
self.status = None
def call_action_1(self):
self.a.do_action_1()
@errorDecorator
def call_action_2(self):
self.a.do_action_2()
a = A()
b = B(a)
while True:
print (b.status)
try:
print("call action 1")
b.call_action_1()
print("call action 2")
b.call_action_2()
except Exception as e:
while True:
try:
print (b.status)
b.call_action_2()
break
except ZeroDivisionError:
time.sleep(3)