Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I return interesting values from a with-statement?

Is there a better way than using globals to get interesting values from a context manager?

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

Other possibilities:

  • singletons

    sort of globals...

  • tuple as an argument to the context manager

    makes the function more specific to a problem /less reusable

  • instance that holds the specific attributes as an argument to the context manager

    same problems as the tuple, but more legible

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

    really bad idea

like image 475
Georg Schölly Avatar asked May 18 '09 13:05

Georg Schölly


2 Answers

See http://docs.python.org/reference/datamodel.html#context-managers

Create a class which holds the success and error counts, and which implements the __enter__ and __exit__ methods.

like image 104
Jonas Kölker Avatar answered Nov 09 '22 21:11

Jonas Kölker


I still think you should be creating a class to hold you error/success counts, as I said in you last question. I'm guessing you have your own class, so just add something like this to it:

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 is None if there are no exceptions once invoking the contextmanager)

And then you probably are already using this somewhere, which will invoke the contextmanager and run your __exit__() code. Edit: As Eli commented, only create a new transaction instance when you want to reset the coutners.

t = transaction()
for q in queries:
    with t:
        t.execute(q)
like image 41
Jason Coon Avatar answered Nov 09 '22 23:11

Jason Coon