Frage

Gibt es einen besseren Weg, als Globals mit interessanten Werte aus einem Kontext-Manager zu bekommen?

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

Weitere Möglichkeiten:

  • Singletons

    Art von Globals ...

  • Tupel als Argument für den Kontext-Manager

    macht die Funktion spezifischer auf ein Problem / weniger wiederverwendbar

  • Instanz, die die spezifischen Eigenschaften als Argument für den Kontext-Manager

    hält

    gleiche Probleme wie das Tupel, aber mehr lesbar

  • eine Ausnahme am Ende des Kontext-Managers erhöht die Werte zu halten.

    wirklich schlechte Idee

War es hilfreich?

Lösung

Siehe http://docs.python.org/reference/datamodel.html # kontext Manager

Erstellen Sie eine Klasse, die den Erfolg und Fehlerzahlen hält, und welche implementiert die __enter__ und __exit__ Methoden.

Andere Tipps

Ich denke immer noch, sollten Sie eine Klasse werden Erstellen Sie Fehler / Erfolg zählt zu halten, wie ich sagte, in Ihnen einen href <= "https://stackoverflow.com/questions/877440/try-except-except-how- zu vermeiden wiederholendes-code "> letzte Frage . Ich schätze, dass Sie Ihre eigene Klasse haben, also nur so etwas wie diese, um es hinzuzufügen:

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 ist keine, wenn es keine Ausnahmen sind, wenn die contextmanager Aufruf)

Und dann sind Sie wahrscheinlich schon diese irgendwo verwenden, die die contextmanager aufrufen und Ihre __exit__() Code ausführen. Edit:. Wie Eli kommentierte erstellen nur eine neue Transaktion Beispiel, wenn Sie die coutners zurücksetzen möchten

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

"Tupel als Argument für den Kontext-Manager

macht die Funktion spezifischer auf ein Problem / weniger wiederverwendbar "

Falsch.

Dies macht den Kontextmanager Zustand beibehalten.

Wenn Sie nichts implementieren mehr als das, wird es wieder verwendbar sein.

Sie können jedoch tatsächlich nicht ein Tupel verwenden, weil es unveränderlich ist. Sie müssen einige wandelbar Sammlung. Wörterbücher und Klassendefinitionen in den Sinn kommen.

Folglich ist die empfohlene Implementierung ist

„Instanz, die die spezifischen Eigenschaften als Argument für den Kontextmanager hält“

Eine einfache Klassendefinition mit zwei Attributen ist alles, was Sie brauchen. Allerdings ist Ihr Transaktionsstatus Stateful und Sie müssen Zustand irgendwo halten.

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top