2016-03-22 10 views
2

Innerhalb einer Funktion eines Wiederholungsmechanismus wie, dass ich mit (immer in einem Try/außer Block):Mit Dekorateur in einer Funktion

 def load(self): 
      [........] 
      # Retry mechanism for locking database 
      for i in range(1, max_connection_retries+1):       
       try: 
        cu.lock() 
        break 
       except LockError as l_error: 
        if i < max_connection_retries: 
         sleep(20) 
         continue 
        else: 
         raise ContinuableError (logger.console(datetime.now().time().strftime ("%b %d %H:%M:%S") + ' ERROR:Impossible to lock the database after %i retries' % max_connection_retries)) 
     [.......] 

Ich verwende diesen Mechanismus mehrmals in anderem Teil der gleiche Funktion und in anderen Funktionen. Es wäre möglich, einen Dekorator nur auf diesen Teil des Codes anzuwenden? etwas wie das:

Wenn ja, könnten Sie mir helfen, mir ein Beispiel eines Dekorators für solch eine Aufgabe zu zeigen?

+2

Dekoratoren funktionieren nur mit Funktionen. Warum würden Sie nicht einfach eine Methode hier verwenden und die Wiederholungsparameter als Argumente übergeben? Es sieht so aus, als würden Sie jedes Mal denselben Code ausführen. –

+0

@KurtStutsman - Ich bin mir nicht sicher über den spezifischen Anwendungsfall des OP, aber ich weiß, dass ich alten Code gesehen habe, wo der 'retry'-Teil für eine Reihe von Funktionen gemacht wurde, und die Wiederholung war agnostisch bezüglich der zugrundeliegenden Funktionalität ('lock',' unlock', 'update',' delete', etc - Datenbankbefehle oder etwas). Dies scheint ein perfekter Anwendungsfall für die Verwendung der "Dekorator" -Funktionalität zu sein, anstatt 10 Methoden mit "maxRetries" zu überladen. Das heißt, Ihr erster Satz ist genau richtig und was das OP braucht, um voranzukommen. – dwanderson

Antwort

3

Die Dekorateur Syntax ist nur syntaktischer Zucker für

# f could be a class as well 
def f(): 
    ... 
f = retry(f) 

Es kann nicht zu beliebigen anonymen Code-Blöcken angewandt werden. Der Hauptzweck eines Dekorators besteht darin, einen Namen erneut zu binden, und ein anonymer Block hat per Definition keinen Namen.

Sie müssten den Code, den Sie wiederholen möchten, in eine Funktion umgestalten, die dekoriert wird. Zum Beispiel sagte

@retry(max=5, message='blablabla') 
def get_lock(): 
    try: 
     cu.lock() 
    except LockError as l_error: 
     # Some action dependent on the implementation of retry 


def load(self): 
    get_lock() 
+0

Danke für Ihre Antwort, ich werde diesen Ansatz versuchen – psagrera

1

Als decorator nur auf Funktion angewandt werden kann, kann aber „Wiederholen“ Logik separate Funktion bewegen und cu.lock/cu.unlock (und andere Sachen wie max, messge) zu dieser Funktion als params übergeben:

def retry(func, tries, message): 
    for i in range(1, tries+1):       
     try: 
      func() # <- call passed function 
      break 
     except LockError as l_error: 
      if i < tries: 
       sleep(20) 
       continue 
      else: 
       raise ContinuableError('...') 

def load(self): 
    retry(cu.lock, tries=5, message='blablabla') # pass cu.lock to be called 

    retry(cu.unlock, tries=5, message='blablabla') # pass cu.unlock to be called