Pergunta

Existe uma maneira melhor do que usar globals para obter valores interessantes de um gerente de contexto?

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

Outras possibilidades:

  • singletons

    tipo de globals ...

  • tupla como um argumento para o gerente de contexto

    faz a função mais específica para um problema / menos reutilizável

  • instância que detém os atributos específicos como um argumento para o gerente de contexto

    mesmos problemas que a tupla, mas mais legível

  • gerar uma exceção no final do gestor contexto segurando os valores.

    péssima idéia

Foi útil?

Solução

http://docs.python.org/reference/datamodel.html # contexto gestores

Crie uma classe que detém as contagens êxito e de erro, e que implementa o __enter__ e __exit__ métodos.

Outras dicas

Eu ainda acho que você deve ser a criação de uma classe para prendê-lo contagem de erro / sucesso, como eu disse em você última pergunta . Eu estou supondo que você tem a sua própria classe, então basta adicionar algo como isso a ele:

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 é Nenhum se não há exceções, uma vez invocando a contextmanager)

E então você provavelmente já estão usando isso em algum lugar, que irá invocar o contextmanager e executar o seu código __exit__(). Editar:. Como Eli comentou, apenas a criar uma nova instância de transação quando você deseja redefinir as coutners

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

"tupla como um argumento para o gerente de contexto

faz a função mais específica para um problema / menos reutilizável "

False.

Isso faz com que o gerente contexto reter estado.

Se você não implementar qualquer coisa mais do que isso, será reutilizável.

No entanto, você não pode realmente usar uma tupla porque é imutável. Você precisa de alguma coleção mutável. Dicionários e definições de classe vêm à mente.

Por isso, a implementação recomendada é

"instância que detém a atributos específicos como um argumento para o gerente de contexto"

Uma definição simples classe com dois atributos é tudo que você precisa. No entanto, o status da transação é stateful e você precisa manter em algum lugar do estado.

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top