Domanda

C'è un modo migliore di utilizzare globali per ottenere i valori interessanti da un contesto manager?

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

Altre possibilità:

  • single

    sorta di variabili globali ...

  • tuple come argomento al contesto Manager

    rende la funzione più specifica a un problema / meno riutilizzabile

  • istanza che contiene gli attributi specifici come argomento al contesto Manager

    stessi problemi del tuple, ma più leggibile

  • genera un'eccezione alla fine del contesto gestore che contiene i valori.

    pessima idea

È stato utile?

Soluzione

http://docs.python.org/reference/datamodel.html # contesto-manager

Creare una classe che detiene i conteggi di successo e di errore, e che implementa i metodi __enter__ e __exit__.

Altri suggerimenti

penso ancora che si dovrebbe essere la creazione di una classe per tenerti conta errore / di successo, come ho detto in voi ultima domanda . Sto indovinando avete la propria classe, quindi basta aggiungere qualcosa di simile ad esso:

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 è Nessuno se non ci sono eccezioni, una volta che invocano il contextmanager)

E allora probabilmente sta già utilizzando questo da qualche parte, che richiamerà l'contextmanager ed eseguire il codice __exit__(). Modifica:. Come ha commentato Eli, solo creare una nuova istanza di transazione quando si desidera ripristinare le coutners

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

"tupla come argomento al contesto Manager

rende la funzione più specifica a un problema / meno riutilizzabile "

False.

In questo modo il manager contesto mantenere lo stato.

Se non implementare qualcosa di più di questo, sarà riutilizzabile.

Tuttavia, non si può effettivamente utilizzare una tupla perché è immutabile. Avete bisogno di qualche collezione mutevole. Dizionari e definizioni di classe vengono in mente.

Di conseguenza, l'implementazione consigliato è

"istanza che contiene gli attributi specifici come argomento al contesto manager"

Una definizione semplice classe con due attributi è tutto ciò che serve. Tuttavia, lo stato di transazione è stateful ed è necessario mantenere lo stato da qualche parte.

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top