Question

Y at-il une meilleure façon que d'utiliser globals pour obtenir des valeurs intéressantes d'un gestionnaire de contexte?

@contextmanager
def transaction():
    global successCount
    global errorCount
    try:
        yield
    except:
        storage.store.rollback()
        errorCount += 1
    else:
        storage.store.commit()
        successCount += 1

Autres possibilités:

  • singletons

    sorte de ... GLOBALS

  • tuple comme argument au gestionnaire de contexte

    rend la fonction plus spécifique à un problème / moins réutilisable

  • instance qui détient les attributs spécifiques comme argument au gestionnaire de contexte

    mêmes problèmes que le tuple, mais plus lisible

  • soulever une exception à la fin du gestionnaire de contexte contenant les valeurs.

    mauvaise idée

Était-ce utile?

La solution

Voir http://docs.python.org/reference/datamodel.html # contexte gestionnaires

Créer une classe qui détient le succès et erreur compte, et qui met en œuvre les méthodes de __enter__ et __exit__.

Autres conseils

Je pense toujours que vous devriez créer une classe pour vous tenir compte erreur / succès, comme je le disais en vous dernier question. Je devine que vous avez votre propre classe, donc il suffit d'ajouter quelque chose comme ça à elle:

class transaction:
    def __init__(self):
        self.errorCount = 0
        self.successCount = 0  

    def __enter__(*args):
        pass  

    def __exit__(self, type, value, traceback):
        if type:
            storage.store.rollback()
            self.errorCount += 1
        else:
            storage.store.commit()
            self.successCount += 1

(type est Aucun s'il n'y a aucune exception en invoquant une fois que le contextmanager)

Et vous utilisez déjà probablement quelque part ce qui appellera l'contextmanager et exécutez votre code __exit__(). Edit:. Eli a commenté, créez seulement une nouvelle instance de transaction lorsque vous souhaitez réinitialiser les coutners

t = transaction()
for q in queries:
    with t:
        t.execute(q)

"tuple comme argument au gestionnaire de contexte

rend la fonction plus spécifique à un problème / moins réutilisable "

Faux.

Cela rend le gestionnaire de contexte conserver l'état.

Si vous ne mettez pas en œuvre quelque chose de plus que cela, il sera réutilisable.

Cependant, vous ne pouvez pas utiliser en fait un tuple parce qu'il est immuable. Vous avez besoin d'une collection mutable. Les dictionnaires et les définitions de classe viennent à l'esprit.

Par conséquent, la mise en œuvre recommandée est

« instance qui contient les attributs spécifiques comme argument au gestionnaire de contexte »

Une définition simple de classe avec deux attributs est tout ce que vous avez besoin. Cependant, l'état de votre transaction est stateful et vous devez conserver quelque part état.

class Counters(dict):
    SUCCEED= 0
    FAIL= 1
    def __init__( self ):
        self[ self.SUCCEED ]= 0
        self[ self.FAIL ]= 0 
    def increment( self, status ):
        self[status] += 1

class Transaction(object):
    def __init__( self, worker, counters ):
        self.worker= worker
        self.counters= counters
    def __enter__( self ):
        self.counters.status= None
    def process( self, *args, **kw ):
        status= self.worker.execute( *args, **kw )
        self.counters.increment( status )
    def __exit__( self ):
        pass

counts= Counters()
for q in queryList:
    with Transaction(execQuery,counts) as t:
        t.process( q )
print counts
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top