from random import randint
import time
state = 0 #close
open_time = 0
failure_count = 0
count = 0
status = {0 : "closed" , 2 : " open" , 1 : "half closed"}
def circuitbreaker(func):
global count
global open_time , state
print("circuit status "+ status.get(state))
if state ==0: #close state
try:
func()
except Exception as ex:
print(ex)
count+=1
if count>2:
print("opening circuit breaker")
state = 2
open_time = int(time.time())
elif (state == 2): #open state
if( time.time() - open_time > 5) :
state = 1
else:
print("circuit opened")
else:
try:
func()
count = 0
open_time = 0
print("closing circuit breaker")
state = 0
except Exception as ex:
state = 2
open_time = int(time.time())
print("opening circuit breaker")
@circuitbreaker
def generic_func():
a = randint(0,9)
print("hello")
print("random number = "+str(a))
if a>4:
return a
else:
raise Exception('Yalla!')
if __name__=="__main__":
# while(True):
# generic_func()
time.sleep(1)
我有此代码。我有几个问题: 1)为什么即使在main中注释了泛型函数也被调用。
2)当我取消注释main函数中的注释部分时。我收到以下错误。如何正确调用此泛型函数。 我的动机是实现一个断路器,该断路器在调用函数中出现某种错误或异常时闭合。我可以直接使用:- 断路器(调用函数),但我想使用装饰器
Traceback (most recent call last):
circuit status closed
hello
File "/Users/abhishekkumar/PycharmProjects/RateLimiter/circuitbreaker.py", line 53, in <module>
random number = 1
Yalla!
generic_func()
TypeError: 'NoneType' object is not callable
Process finished with exit code 1
问题在于装饰器应该返回一个函数对象,并且应该在函数内部具有相关的逻辑,然后返回该函数,否则它不返回任何对象
答案 0 :(得分:2)
问题1的答案:这是因为断路器装饰器,因为其逻辑是在模块导入期间执行的,并调用了装饰的功能。检查以下几行
...
try:
func() # <-- here
except Exception as ex:
print(ex)
...
实现装饰器的方法是返回一个包装函数,其中包含业务逻辑:
from functools import wraps
def decorator(f):
@wraps(f)
def wrapper(*args, **kwargs):
... your logic here ...
return wrapper
第2个问题的答案来自上一个。
答案 1 :(得分:1)
Answers to almost all questions you never asked about decorators
装饰某物的函数应该返回其自身功能的函数-不是做所有事情-您不是在返回“ functionpointer”,而是返回一个隐式None
您的灭杀者(隐含的是您什么也不返回)。然后将此None
称为...
如何解决:
def circuitbreaker(func):
def the_works():
global count
global open_time , state
print("circuit status "+ status.get(state))
# .. all your other code ...
return the_works
for _ in range(5):
generic_func()
修订输出:
circuit status closed
hello
random number = 3
Yalla!
circuit status closed
hello
random number = 3
Yalla!
circuit status closed
hello
random number = 0
Yalla!
opening circuit breaker
circuit status open
circuit opened
circuit status open
circuit opened
答案 2 :(得分:1)
circuitbreaker
中,您已经调用了generic_func
。 Here是Fluent Python的示例:
registry = []
def register(func):
print('running register(%s)' % func)
registry.append(func)
return func
@register
def f1():
print('running f1()')
@register
def f2():
print('running f2()')
def f3():
print('running f3()')
def main():
print('registry ->', registry)
f1()
f2()
f3()
if __name__ == '__main__':
main()
输出为
running register(<function f1 at 0x1055ae378>)
running register(<function f2 at 0x1055ae400>)
registry -> [<function f1 at 0x1055ae378>, <function f2 at 0x1055ae400>]
running f1()
running f2()