views:

577

answers:

2

How do I use thread local storage in Python?

Related

A: 

As noted in the question, Alex Martelli gives a solution here. This function allows us to use a factory function to generate a default value for each thread.

#Code originally posted by Alex Martelli
#Modified to use standard Python variable name conventions
import threading
threadlocal = threading.local()    

def threadlocal_var(varname, factory, *args, **kwargs):
  v = getattr(threadlocal, varname, None)
  if v is None:
    v = factory(*args, **kwargs)
    setattr(threadlocal, varname, v)
  return v
Casebash
If you're doing this, what you really want is probably defaultdict + ThreadLocalDict, but I don't think there's a stock implementation of this. (defaultdict should really be part of dict, eg. `dict(default=int)`, which would eliminate the need for a "ThreadLocalDefaultDict".)
Glenn Maynard
@Glenn, the problem with `dict(default=int)` is that the `dict()` constructor takes in kwargs and adds them to the dict. So if that was implemented, people wouldn't be able to specify a key called 'default'. But I actually think this is a small price to pay for an implementation like you show. After all, there are other ways to add a key to a dict.
Evan Fosmark
@Evan - I agree that this design would be better, but it would break backwards compatibility
Casebash
@Glenn, I use this approach for plenty of thread-local variables that *AREN'T* `defaultdict`s, if that's what you mean. If you mean that this has a similar interface to what `defaultdict` SHOULD have (providing optional positional and named args to the factory function: EVERY time you can store a callback you SHOULD be able to optionally pass args for it!-), then, sorta, except that I typically use different factories-and-args for different varnames, AND the approach I give also works fine on Python 2.4 (don't ask...!-).
Alex Martelli
+1  A: 

Can also write

import threading
mydata = threading.local()
mydata.x = 1

mydata.x will only exist in the current thread

Casebash
Rather than putting this sort of code in its own answer, why not just edit your question?
Evan Fosmark
@Evan: Because there are two basic approaches, which are really separate answers
Casebash