[docs] [issue24020] threading.local() must be run at module level (doc improvement)

Paul Moore report at bugs.python.org
Wed Apr 22 00:29:57 CEST 2015


Paul Moore added the comment:

On 21 April 2015 at 23:11, Ethan Furman <report at bugs.python.org> wrote:
> Hmmm... could my problem be that even though function locals are thread-safe, the globals are not, so trying to create a threading.local via a global statement was clobbering other threading.local instances?  While that would make sense, I'm still completely clueless why having a single global statement, which (apparently) creates a single threading.local object, could be distinct for all the threads... unless, of course, it can detect which thread is accessing it and react appropriately.  Okay, that's really cool.

You're not creating a single threading object. You're creating one
each call() and overwriting the old one.

> So I was doing two things wrong:
> - calling threading.local() inside a function (although this would
>   probably work if I then passed that object around, as I do not
>   need to persist state across function calls -- wait, that would
>   be the same as using an ordinary, function-local dict, wouldn't
>   it?)

Yes, a dict should be fine if you're only using it within the one function call.

> - attempting to assign the threading.local object to a global
>   variable from inside a function (this won't work, period)

It does work, it's just there isn't *the* object, there's lots and you
keep overwriting.

The thread safety issue is that if you write over the global in one
thread, before another thread has finished, you lose the second
thread's values (because they were on the old, lost, namespace. So
basically you'd see unpredictable, occasional losses of all your
CONTEXT vars in a thread.

> Many thanks for helping me figure that out.

(If you did :-) - hope the clarifications above helped).

> Paul, in your SO answer you state:
> ---------------------------------
> Just like an ordinary object, you can create multiple threading.local instances in your code. They can be local variables, class or instance members, or global variables.
>
> - Local variables are already thread-safe, aren't they?  So there
>   would be no point in using threading.local() there.

Not unless you're going to return them from your function, or
something like that. But yes, it's unlikely they will be needed there.
I only mentioned it to avoid giving any impression that "only set at
global scope" was important.

> - Instance members (set from __init__ of someother method): wouldn't
>   that be the same problem I was having trying to update a
>   non-threadsafe global with a new threading.local() each time?

You'd set vars on the namespace held in the instance variable. It's
much like the local variable case, except you are more likely to pass
an instance around between threads.

> It seems to me the take-away here is that you only want to create a threading.local() object /once/ -- if you are creating the same threading.local() object more than once, you're doing it wrong.

Well, sort of. You can only create *any* object once :-) There seems
to be a confusion (in the SO thread and with you, maybe) that
threading.local objects are somehow singletons in that you "create"
them repeatedly and get the same object. That's just wrong - they are
entirely normal objects, that you can set arbitrary attributes on. The
only difference is that each thread sees an independent set of
attributes on the object.

----------

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue24020>
_______________________________________


More information about the docs mailing list