Pregunta

¿Hay una mejor manera de utilizar variables globales para obtener valores interesantes desde un gestor de contexto?

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

Otras posibilidades:

  • únicos

    tipo de variables globales ...

  • tupla como argumento para el gestor de contexto

    hace que la función más específica a un problema / menos reutilizable

  • instancia que contiene los atributos específicos como argumento para el gestor de contexto

    mismos problemas que la tupla, pero más legible

  • elevar una excepción al final del gestor de contexto que tiene los valores.

    muy mala idea

¿Fue útil?

Solución

http://docs.python.org/reference/datamodel.html # de contexto-gerentes

Crea una clase que tiene el éxito y error conteos, y que implementa los métodos __enter__ y __exit__.

Otros consejos

Todavía pienso que debe ser la creación de una clase para sostener que los recuentos de error / éxito, como dije en el que última pregunta . Supongo que usted tiene su propia clase, por lo que sólo tiene que añadir algo como esto a ella:

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 es Ninguno si no hay excepciones, una vez que invocan la contextmanager)

Y entonces es probable que ya está usando esto en alguna parte, que invocará el contextmanager y ejecutar su código __exit__(). Editar:. Como se comentó Eli, sólo para crear una nueva instancia de transacción cuando se desea restablecer los coutners

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

"tupla como argumento para el gestor de contexto

hace la función más específica a un problema / menos reutilizable "

Falso.

Esto hace que el gestor de contexto retener estado.

Si no se implementa nada más que esto, será reutilizable.

Sin embargo, no se puede utilizar realmente una tupla porque es inmutable. Es necesario alguna colección mutable. Diccionarios y definiciones de clases vienen a la mente.

En consecuencia, la puesta en práctica recomendada es

"instancia que contiene los atributos específicos como argumento para el gestor de contexto"

Una definición de clase simple con dos atributos es todo lo que necesita. Sin embargo, el estado de la transacción es de estado y hay que conservar el estado en alguna 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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top