Search code examples
pythonpython-2.7gevent

how to use gevent local module


I'm trying to use gevent.local module to have a greenlet context. Following the example in: http://www.gevent.org/gevent.local.html I tried this sample code:

#!env python

import gevent
from gevent import local

def foo():
    print("IN FOO")
    data = local.local()
    data.numbers = 42

    bar()

def bar():
    print("IN BAR")
    data = local.local()
    print(data.numbers)


def main():
    foo_gl = gevent.Greenlet(foo)
    print("starting foo")
    foo_gl.start()
    gevent.joinall([foo_gl])

if __name__ == "__main__":
    main()

But I get an error:

$ mytest/local.py
starting foo
IN FOO
IN BAR
Traceback (most recent call last):
  File "/Users/me/.virtualenvs/sorites/lib/python2.7/site-packages/gevent/greenlet.py", line 327, in run
    result = self._run(*self.args, **self.kwargs)
  File "gl_test/local.py", line 11, in foo
    bar()
  File "gl_test/local.py", line 16, in bar
    print(data.numbers)
  File "/Users/me/.virtualenvs/sorites/lib/python2.7/site-packages/gevent/local.py", line 186, in __getattribute__
    return object.__getattribute__(self, name)
AttributeError: 'local' object has no attribute 'numbers'
<Greenlet at 0x1053b2410: foo> failed with AttributeError

What am I missing here? Thanks!


Solution

  • Because you declare the variable data in the function foo(), it will be recognized as a local variable which can not be used in another function.

    And the variable data declared in the function bar() is an another local variable, which has nothing to do with the variable data declared in the function foo()

    Code

    #!env python
    
    import gevent
    from gevent import local
    
    def foo():
        print("IN FOO")
        data = local.local()
        #This line of code declares data as a local variable.
        data.numbers = 42
    
        bar()
    
    def bar():
        print("IN BAR")
        data = local.local()
        #This line of code declares data as an another local variable.
        print(data.numbers)
    
    
    def main():
        foo_gl = gevent.Greenlet(foo)
        print("starting foo")
        foo_gl.start()
        gevent.joinall([foo_gl])
    
    if __name__ == "__main__":
        main()
    

    The following is the code which shows that how the gevent.local module works.

    You can find out that even the variable data is declared as a global variable, it will not be affected in one greenlet when you modified the same variable in another greenlet. That means you can use the variable as a local variable in each greenlet without declaring it as a local variable again.

    Hope it helps.

    Modified Code

    #!env python
    
    import gevent
    from gevent import local
    
    data = local.local()
    data.numbers = 12
    #Declare data as a global variable.
    
    def foo():
        print("IN FOO")
        data.numbers = 42
        #Change the value of data.numbers.
    
        print(data.__dict__)
        #Check the values in data in the function foo.
    
    def bar():
        print("IN BAR")
    
        print(data.__dict__)
        #Check the values in data in the function bar.
    
    
    def main():
        print("In Main")
        print(data.__dict__)
        #Check the values in data at beginning.
    
        foo_gl = gevent.Greenlet(foo)
        bar_gl = gevent.Greenlet(bar)
        foo_gl.start()
        bar_gl.start()
        gevent.joinall([foo_gl, bar_gl])
    
        print("Afeter all, In Main")
        print(data.__dict__)
        #Check the values in data at the end.
    
    if __name__ == "__main__":
        main()