Trying to use threading.local()
MRAB
python at mrabarnett.plus.com
Wed Sep 12 15:44:36 EDT 2018
On 2018-09-12 17:16, Steven D'Aprano wrote:
> I'm originally posted this on the Python-Ideas list, but this is probably
> more appropriate.
>
>
> import time
> from threading import Thread, local
>
> def func():
> pass
>
> def attach(value):
> func.__params__ = local()
> func.__params__.value = value
>
>
> def worker(i):
> print("called from thread %s" % i)
> attach(i)
> assert func.__params__.value == i
> time.sleep(3)
> value = func.__params__.value
> if value != i:
> print("mismatch", i, value)
>
> for i in range(5):
> t = Thread(target=worker, args=(i,))
> t.start()
>
> print()
>
>
>
>
>
> When I run that, each of the threads print their "called from ..."
> message, the assertions all pass, then a couple of seconds later they
> consistently all raise exceptions:
>
> Exception in thread Thread-1:
> Traceback (most recent call last):
> File "/usr/local/lib/python3.5/threading.py", line 914, in
> _bootstrap_inner
> self.run()
> File "/usr/local/lib/python3.5/threading.py", line 862, in run
> self._target(*self._args, **self._kwargs)
> File "<stdin>", line 5, in worker
> AttributeError: '_thread._local' object has no attribute 'value'
>
>
>
> What am I doing wrong?
>
I've changed the code to:
import time
from threading import Thread, local
def func():
pass
def attach(value):
func.__params__ = local()
func.__params__.value = value
def worker(i):
print("called from thread %s" % i)
attach(i)
print('thread %s before sleep => %s' % (i, func.__params__))
assert func.__params__.value == i
time.sleep(1)
print('thread %s after sleep => %s' % (i, func.__params__))
time.sleep(1)
print('thread %s finally => %s' % (i, func.__params__))
print('stored value for thread %s is %s' % (i,
getattr(func.__params__, 'value', 'MISSING')))
for i in range(2):
t = Thread(target=worker, args=(i,))
t.start()
print()
My output is:
called from thread 0
thread 0 before sleep => <_thread._local object at 0x0000014936FB8C50>
called from thread 1
thread 1 before sleep => <_thread._local object at 0x0000014936FB8CA8>
thread 1 after sleep => <_thread._local object at 0x0000014936FB8CA8>
thread 0 after sleep => <_thread._local object at 0x0000014936FB8CA8>
thread 0 finally => <_thread._local object at 0x0000014936FB8CA8>
stored value for thread 0 is MISSING
thread 1 finally => <_thread._local object at 0x0000014936FB8CA8>
stored value for thread 1 is 1
Note that thread 1 is overwriting the reference to the thread-local
storage of thread 0.
It looks like what's happening is that thread 0 ends up trying to read
the storage for thread 1, but as it's for a different thread, the
contents aren't visible to it.
More information about the Python-list
mailing list