How can I return interesting values ​​from an operator with an expression?

Is there a better way than using global variables to get interesting values ​​from the context manager?

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

Other features:

  • loners

    kind of global characters ...

  • tuple as an argument to the context manager

    makes the function more problem specific / less reusable

  • an instance that contains certain attributes as an argument to the context manager

    same problems as tuple but more picky

  • raise an exception at the end of the context manager containing the values.

    really bad idea

+3
source share
3 answers

, , /, . , , - :

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 - None, contextmanager)

, , -, contextmanager __exit__(). :. , , reset coutners.

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

"

/ "

False.

, .

If you do not implement anything else, it will be reused.

However, you cannot use a tuple because it is immutable. You need some kind of volatile collection. Dictionaries and class definitions come to mind.

Therefore, the recommended implementation

"which contains certain attributes as an argument to the context manager"

A simple class definition with two attributes is all you need. However, the transaction status is wealthy, and you need to save the state somewhere.

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
-1
source

Source: https://habr.com/ru/post/1708557/