繁体   English   中英

Python装饰器

[英]Python decorator

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)当我取消注释主要功能部分。 我收到以下错误。如何正确调用此泛型函数。 我的动机是实现一个断路器,该断路器在调用函数中出现某种错误或异常时闭合。 我可以直接使用:-circuitbreaker(calling function)但我想使用装饰器

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

问题是装饰器应该返回一个函数对象,并且应该在函数内部具有相关的逻辑,然后返回该函数,否则它将不返回任何对象

问题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的答案来自上一个。

回答几乎从未询问过的关于装饰的所有问题

装饰某物的函数应该返回它本身所做的功能- 不做所有事情-您不是在返回“功能指针”,而是从清除程序中隐式返回None (隐式为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
  1. 装饰器在定义装饰功能后立即运行,通常在导入时运行。 在装饰器circuitbreaker ,您已经调用了generic_func

是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()
  1. 这是您想要的吗: 如何在装饰器中捕获异常,但又允许调用者也捕获该异常?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM