# gevent

# `gevent.local` – Greenlet-local objects

Greenlet-local objects.

This module is based on _threading_local.py from the standard library of Python 3.4.

Greenlet-local objects support the management of greenlet-local data. If you have data that you want to be local to a greenlet, simply create a greenlet-local object and use its attributes:

    >>> import gevent
    >>> from gevent.local import local
    >>> mydata = local()
    >>> mydata.number = 42
    >>> mydata.number
    42

You can also access the local-object’s dictionary:

    >>> mydata.__dict__
    {'number': 42}
    >>> mydata.__dict__.setdefault('widgets', [])
    []
    >>> mydata.widgets
    []

What’s important about greenlet-local objects is that their data are local to a greenlet. If we access the data in a different greenlet:

    >>> log = []
    >>> def f():
    ...     items = list(mydata.__dict__.items())
    ...     items.sort()
    ...     log.append(items)
    ...     mydata.number = 11
    ...     log.append(mydata.number)
    >>> greenlet = gevent.spawn(f)
    >>> greenlet.join()
    >>> log
    [[], 11]

we get different data. Furthermore, changes made in the other greenlet don’t affect data seen in this greenlet:

    >>> mydata.number
    42

Of course, values you get from a local object, including a __dict__ attribute, are for whatever greenlet was current at the time the attribute was read. For that reason, you generally don’t want to save these values across greenlets, as they apply only to the greenlet they came from.

You can create custom local objects by subclassing the local class:

    >>> class MyLocal(local):
    ...     number = 2
    ...     initialized = False
    ...     def __init__(self, **kw):
    ...         if self.initialized:
    ...             raise SystemError('__init__ called too many times')
    ...         self.initialized = True
    ...         self.__dict__.update(kw)
    ...     def squared(self):
    ...         return self.number ** 2

This can be useful to support default values, methods and initialization. Note that if you define an __init__ method, it will be called each time the local object is used in a separate greenlet. This is necessary to initialize each greenlet’s dictionary.

Now if we create a local object:

    >>> mydata = MyLocal(color='red')

Now we have a default number:

    >>> mydata.number
    2

an initial color:

    >>> mydata.color
    'red'
    >>> del mydata.color

And a method that operates on the data:

    >>> mydata.squared()
    4

As before, we can access the data in a separate greenlet:

    >>> log = []
    >>> greenlet = gevent.spawn(f)
    >>> greenlet.join()
    >>> log
    [[('color', 'red'), ('initialized', True)], 11]

without affecting this greenlet’s data:

    >>> mydata.number
    2
    >>> mydata.color
    Traceback (most recent call last):
    ...
    AttributeError: 'MyLocal' object has no attribute 'color'

Note that subclasses can define slots, but they are not greenlet local. They are shared across greenlets:

    >>> class MyLocal(local):
    ...     __slots__ = 'number'

    >>> mydata = MyLocal()
    >>> mydata.number = 42
    >>> mydata.color = 'red'

So, the separate greenlet:

    >>> greenlet = gevent.spawn(f)
    >>> greenlet.join()

affects what we see:

    >>> mydata.number
    11

    >>> del mydata

Changed in version 1.1a2: Update the implementation to match Python 3.4 instead of Python 2.5. This results in locals being eligible for garbage collection as soon as their greenlet exits.

Changed in version 1.2.3: Use a weak-reference to clear the greenlet link we establish in case the local object dies before the greenlet does.

Changed in version 1.3a1: Implement the methods for attribute access directly, handling descriptors directly here. This allows removing the use of a lock and facilitates greatly improved performance.

Changed in version 1.3a1: The `__init__` method of subclasses of `local` is no longer called with a lock held. CPython does not use such a lock in its native implementation. This could potentially show as a difference if code that uses multiple dependent attributes in `__slots__` (which are shared across all greenlets) switches during `__init__`.

class local(*args, **kw)

  Bases: `object`

  An object whose attributes are greenlet-local.

Next page: `gevent.lock` – Locking primitives