Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Local Variables Inside a Python Generator

How would you access a local variable defined inside a Python generator from outside the generator?

I have a case where my generator manipulates a local state, and for unittests I want to inspect this state to ensure it contains the correct values.

I can't store the state to an instance variable (e.g. self.state = blah), because I might be creating multiple generators from the same class instance, meaning the generators might overwrite each other's state. I also can't return the state in the yield expression, because the state name may change or vary because individual generator instances.

e.g. I want to do something like this (albeit this code doesn't work)

from random import random

class MyIter(object):
    def __iter__(self):
        context = {}
        for i in xrange(10):
            context[random()] = random()
            yield i

obj = MyIter()
i1 = iter(obj)
i2 = iter(obj)
while 1:
    try:
        i1.next()
        i2.next()
        print i1.context
        print i2.context
    except StopIteration:
        break

Is there anyway to access local variables by inspecting Python's execution stack?

like image 235
Cerin Avatar asked Jan 19 '11 14:01

Cerin


1 Answers

Sorry to answer my own question, but after digging into the generator interface, I found the exact path I need to access the generator's local variables:

from random import random

class MyIter(object):
    def __iter__(self):
        context = {}
        for i in xrange(10):
            context[random()] = random()
            yield i

obj = MyIter()
i1 = iter(obj)
i2 = iter(obj)
while 1:
    try:
        i1.next()
        i2.next()
        print i1.gi_frame.f_locals['context']
        print i2.gi_frame.f_locals['context']
    except StopIteration:
        break
like image 96
Cerin Avatar answered Sep 27 '22 20:09

Cerin