Hi Andy, this is a messy corner of threading, gevent, and python. I'll
do my best to outline what's going on.
To begin with, python has a feature called thread local storage.
Classes that inherit from threading.local result in objects that
appear 'local' to each thread, i.e. they don't share attributes
between threads. Each thread can read and write its own values to the
local storage object independently. Python ships with two
implementations of thread local storage: the native one, which is used
by default, and a pure-python one, which is in _threading_local.local.
When gevent patches python's threading implementation, it attempts to
switch threading.local to the pure-python _threading_local.local
instead of the native implementation. It does so because the native
thread local storage won't work with gevent's greenlet-based threads.
However, it doesn't seem to patch correctly
(
http://code.google.com/p/gevent/issues/detail?id=24). There's a
workaround:
---
import gevent.monkey
gevent.monkey.patch_all()
import threading
# now the workaround: patch threading.local with the pure-python
implementation (gevent should've done this for us in
monkey.patch_threads())
import _threading_local
threading.local = _threading_local.local
---
On top of this, some pythons shipped with a broken
_threading_local.local (
http://bugs.python.org/issue1522237). So, you
have to make sure you've got a working one.
Lastly, if you get threading.local patched with a working
_threading_local.local, thread local objects will ONLY work with
greenlet-based threads, and won't work with plain greenlets. If your
library or code makes use of threading.Thread or thread.Thread et al,
then thread local storage will work as expected. If, however, you're
not using threads and you're only using greenlets, you'll find that
thread local objects aren't greenlet local. In other words, plain
greenlets that access an object that mixes in threading.local won't
see separate sets of attributes, they'll be dealing with exactly the
same object. If that's the situation you find yourself in, you can
patch your threading.local with eventlet's corolocal.py, which will
make thread local objects work with all greenlets (whether they
underlie a thread or not). That might look like this:
---
import gevent.monkey
gevent.monkey.patch_all()
import threading
# ok, now replace threading.local with a version that works with all greenlets
import corolocal # find this from
http://pastebin.com/W4cyt42i
threading.local = corolocal.local
---
So, in summary, there are three issues:
1. gevent doesn't patch threading.local as it intends to
(
http://code.google.com/p/gevent/issues/detail?id=24)
2. even if gevent patches threading.local correctly, your python's
_threading_local.local might be broken
(
http://bugs.python.org/issue1522237)
3. even if gevent patches threading.local correctly, and your python's
_threading_local.local works, thread local objects won't work with
plain greenlets (they only work with greenlet-based threads).
Phew.
If you're trying to get something specific working, feel free to email
the list with the particular issue / library / etc and someone might
be able to help.
Ted