Python оформитель - PullRequest
       13

Python оформитель

0 голосов
/ 13 декабря 2018
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), когда я раскомментирую закомментированную часть в главной функции.Я получаю следующую ошибку. Как правильно вызвать эту универсальную функцию?Мой мотив состоит в том, чтобы реализовать автоматический выключатель, который замыкается при возникновении какой-либо ошибки или исключения в вызывающей функции.Я могу напрямую использовать: - автоматический выключатель (вызывающая функция), но я хотел использовать декораторы

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

Проблема заключалась в том, что декоратор должен возвращать объект функции и иметь соответствующую логику внутри функции, а затем возвращать эту функциюв противном случае он не возвращает ни одного объекта

Ответы [ 3 ]

0 голосов
/ 13 декабря 2018
  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()
Это то, что вы хотите: Как мне перехватить исключение в декораторе, но разрешить вызывающему также его перехватить?
0 голосов
/ 13 декабря 2018

ответ на вопрос № 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 происходит изпредыдущий.

0 голосов
/ 13 декабря 2018

Ответы почти на все вопросы, которые вы никогда не задавали о декораторах

Функция, которая украшает что-то, должна возвращать функцию того, что она делает сама, а не делать все вещи - вы не возвращаете «указатель функции», а неявно 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
...