2016-03-29 3 views
1

J'essaie de cacher quelques tentatives/hors complexité avec un gestionnaire de contexte. Voici un exemple simple:Utilisation de yield deux fois dans contextmanager

from contextlib import contextmanager 
import mpd 

mpdclient = mpd.MPDClient() 
mpdclient.connect("localhost", 6600) 

@contextmanager 
def mpdcontext(): 
    try: 
    yield 
    except mpd.ConnectionError: 
    mpdclient.connect("localhost", 6600) 

with mpdcontext(): 
    mpdclient.status() 

with mpdcontext(): 
    mpdclient.lsinfo() 

Maintenant, comme je l'ai compris, le bloc dans l'instruction with est exécutée lorsque le rendement est appelé. Dans mon cas, si cela déclenche une exception, je me reconnecte à mpd. Puis-je d'une manière ou d'une autre exécuter le bloc-bloc après cette reconnexion?

Merci

Répondre

5

Réponse courte est que vous ne pouvez pas céder deux fois d'un gestionnaire de contexte. Vous pourriez envisager d'utiliser un décorateur qui enveloppe ce que vous essayez d'exécuter et réessayer et reconnecter un certain nombre de fois avant d'abandonner. Voici un exemple trivial (utilisation non-production) juste pour illustrer:

import mpd 
import functools 

HOST = "localhost" 
PORT = 6600 
mpdclient = mpd.MPDClient() 
mpdclient.connect(HOST, PORT) 

def withreconnect(retries=1): 
    def _wrapper(func): 
     @functools.wraps(func) 
     def wrapped(*args, **kwargs): 
      for _ in range(retries + 1): # Loop retries + first attempt 
       try: 
        return func(*args, **kwargs) 
       except mpd.ConnectionError: 
        mpdclient.connect(HOST, PORT) 
     return _wrapped 
    return wrapped 

@withreconnect() # Reconnect 1 time, default 
def status(): 
    mpdclient.status() 

@withreconnect(retries=3) # Reconnect 3 times 
def lsinfo(): 
    mpdclient.lsinfo() 

Modifier: appel ajouté au décorateur, dans le cas sans argument