Edit File by line
/home/barbar84/www/wp-conte.../plugins/sujqvwi/AnonR/anonr.TX.../usr/lib64/python3....
File: _threading_local.py
"""Thread-local objects.
[0] Fix | Delete
[1] Fix | Delete
(Note that this module provides a Python version of the threading.local
[2] Fix | Delete
class. Depending on the version of Python you're using, there may be a
[3] Fix | Delete
faster one available. You should always import the `local` class from
[4] Fix | Delete
`threading`.)
[5] Fix | Delete
[6] Fix | Delete
Thread-local objects support the management of thread-local data.
[7] Fix | Delete
If you have data that you want to be local to a thread, simply create
[8] Fix | Delete
a thread-local object and use its attributes:
[9] Fix | Delete
[10] Fix | Delete
>>> mydata = local()
[11] Fix | Delete
>>> mydata.number = 42
[12] Fix | Delete
>>> mydata.number
[13] Fix | Delete
42
[14] Fix | Delete
[15] Fix | Delete
You can also access the local-object's dictionary:
[16] Fix | Delete
[17] Fix | Delete
>>> mydata.__dict__
[18] Fix | Delete
{'number': 42}
[19] Fix | Delete
>>> mydata.__dict__.setdefault('widgets', [])
[20] Fix | Delete
[]
[21] Fix | Delete
>>> mydata.widgets
[22] Fix | Delete
[]
[23] Fix | Delete
[24] Fix | Delete
What's important about thread-local objects is that their data are
[25] Fix | Delete
local to a thread. If we access the data in a different thread:
[26] Fix | Delete
[27] Fix | Delete
>>> log = []
[28] Fix | Delete
>>> def f():
[29] Fix | Delete
... items = sorted(mydata.__dict__.items())
[30] Fix | Delete
... log.append(items)
[31] Fix | Delete
... mydata.number = 11
[32] Fix | Delete
... log.append(mydata.number)
[33] Fix | Delete
[34] Fix | Delete
>>> import threading
[35] Fix | Delete
>>> thread = threading.Thread(target=f)
[36] Fix | Delete
>>> thread.start()
[37] Fix | Delete
>>> thread.join()
[38] Fix | Delete
>>> log
[39] Fix | Delete
[[], 11]
[40] Fix | Delete
[41] Fix | Delete
we get different data. Furthermore, changes made in the other thread
[42] Fix | Delete
don't affect data seen in this thread:
[43] Fix | Delete
[44] Fix | Delete
>>> mydata.number
[45] Fix | Delete
42
[46] Fix | Delete
[47] Fix | Delete
Of course, values you get from a local object, including a __dict__
[48] Fix | Delete
attribute, are for whatever thread was current at the time the
[49] Fix | Delete
attribute was read. For that reason, you generally don't want to save
[50] Fix | Delete
these values across threads, as they apply only to the thread they
[51] Fix | Delete
came from.
[52] Fix | Delete
[53] Fix | Delete
You can create custom local objects by subclassing the local class:
[54] Fix | Delete
[55] Fix | Delete
>>> class MyLocal(local):
[56] Fix | Delete
... number = 2
[57] Fix | Delete
... def __init__(self, **kw):
[58] Fix | Delete
... self.__dict__.update(kw)
[59] Fix | Delete
... def squared(self):
[60] Fix | Delete
... return self.number ** 2
[61] Fix | Delete
[62] Fix | Delete
This can be useful to support default values, methods and
[63] Fix | Delete
initialization. Note that if you define an __init__ method, it will be
[64] Fix | Delete
called each time the local object is used in a separate thread. This
[65] Fix | Delete
is necessary to initialize each thread's dictionary.
[66] Fix | Delete
[67] Fix | Delete
Now if we create a local object:
[68] Fix | Delete
[69] Fix | Delete
>>> mydata = MyLocal(color='red')
[70] Fix | Delete
[71] Fix | Delete
Now we have a default number:
[72] Fix | Delete
[73] Fix | Delete
>>> mydata.number
[74] Fix | Delete
2
[75] Fix | Delete
[76] Fix | Delete
an initial color:
[77] Fix | Delete
[78] Fix | Delete
>>> mydata.color
[79] Fix | Delete
'red'
[80] Fix | Delete
>>> del mydata.color
[81] Fix | Delete
[82] Fix | Delete
And a method that operates on the data:
[83] Fix | Delete
[84] Fix | Delete
>>> mydata.squared()
[85] Fix | Delete
4
[86] Fix | Delete
[87] Fix | Delete
As before, we can access the data in a separate thread:
[88] Fix | Delete
[89] Fix | Delete
>>> log = []
[90] Fix | Delete
>>> thread = threading.Thread(target=f)
[91] Fix | Delete
>>> thread.start()
[92] Fix | Delete
>>> thread.join()
[93] Fix | Delete
>>> log
[94] Fix | Delete
[[('color', 'red')], 11]
[95] Fix | Delete
[96] Fix | Delete
without affecting this thread's data:
[97] Fix | Delete
[98] Fix | Delete
>>> mydata.number
[99] Fix | Delete
2
[100] Fix | Delete
>>> mydata.color
[101] Fix | Delete
Traceback (most recent call last):
[102] Fix | Delete
...
[103] Fix | Delete
AttributeError: 'MyLocal' object has no attribute 'color'
[104] Fix | Delete
[105] Fix | Delete
Note that subclasses can define slots, but they are not thread
[106] Fix | Delete
local. They are shared across threads:
[107] Fix | Delete
[108] Fix | Delete
>>> class MyLocal(local):
[109] Fix | Delete
... __slots__ = 'number'
[110] Fix | Delete
[111] Fix | Delete
>>> mydata = MyLocal()
[112] Fix | Delete
>>> mydata.number = 42
[113] Fix | Delete
>>> mydata.color = 'red'
[114] Fix | Delete
[115] Fix | Delete
So, the separate thread:
[116] Fix | Delete
[117] Fix | Delete
>>> thread = threading.Thread(target=f)
[118] Fix | Delete
>>> thread.start()
[119] Fix | Delete
>>> thread.join()
[120] Fix | Delete
[121] Fix | Delete
affects what we see:
[122] Fix | Delete
[123] Fix | Delete
>>> mydata.number
[124] Fix | Delete
11
[125] Fix | Delete
[126] Fix | Delete
>>> del mydata
[127] Fix | Delete
"""
[128] Fix | Delete
[129] Fix | Delete
from weakref import ref
[130] Fix | Delete
from contextlib import contextmanager
[131] Fix | Delete
[132] Fix | Delete
__all__ = ["local"]
[133] Fix | Delete
[134] Fix | Delete
# We need to use objects from the threading module, but the threading
[135] Fix | Delete
# module may also want to use our `local` class, if support for locals
[136] Fix | Delete
# isn't compiled in to the `thread` module. This creates potential problems
[137] Fix | Delete
# with circular imports. For that reason, we don't import `threading`
[138] Fix | Delete
# until the bottom of this file (a hack sufficient to worm around the
[139] Fix | Delete
# potential problems). Note that all platforms on CPython do have support
[140] Fix | Delete
# for locals in the `thread` module, and there is no circular import problem
[141] Fix | Delete
# then, so problems introduced by fiddling the order of imports here won't
[142] Fix | Delete
# manifest.
[143] Fix | Delete
[144] Fix | Delete
class _localimpl:
[145] Fix | Delete
"""A class managing thread-local dicts"""
[146] Fix | Delete
__slots__ = 'key', 'dicts', 'localargs', 'locallock', '__weakref__'
[147] Fix | Delete
[148] Fix | Delete
def __init__(self):
[149] Fix | Delete
# The key used in the Thread objects' attribute dicts.
[150] Fix | Delete
# We keep it a string for speed but make it unlikely to clash with
[151] Fix | Delete
# a "real" attribute.
[152] Fix | Delete
self.key = '_threading_local._localimpl.' + str(id(self))
[153] Fix | Delete
# { id(Thread) -> (ref(Thread), thread-local dict) }
[154] Fix | Delete
self.dicts = {}
[155] Fix | Delete
[156] Fix | Delete
def get_dict(self):
[157] Fix | Delete
"""Return the dict for the current thread. Raises KeyError if none
[158] Fix | Delete
defined."""
[159] Fix | Delete
thread = current_thread()
[160] Fix | Delete
return self.dicts[id(thread)][1]
[161] Fix | Delete
[162] Fix | Delete
def create_dict(self):
[163] Fix | Delete
"""Create a new dict for the current thread, and return it."""
[164] Fix | Delete
localdict = {}
[165] Fix | Delete
key = self.key
[166] Fix | Delete
thread = current_thread()
[167] Fix | Delete
idt = id(thread)
[168] Fix | Delete
def local_deleted(_, key=key):
[169] Fix | Delete
# When the localimpl is deleted, remove the thread attribute.
[170] Fix | Delete
thread = wrthread()
[171] Fix | Delete
if thread is not None:
[172] Fix | Delete
del thread.__dict__[key]
[173] Fix | Delete
def thread_deleted(_, idt=idt):
[174] Fix | Delete
# When the thread is deleted, remove the local dict.
[175] Fix | Delete
# Note that this is suboptimal if the thread object gets
[176] Fix | Delete
# caught in a reference loop. We would like to be called
[177] Fix | Delete
# as soon as the OS-level thread ends instead.
[178] Fix | Delete
local = wrlocal()
[179] Fix | Delete
if local is not None:
[180] Fix | Delete
dct = local.dicts.pop(idt)
[181] Fix | Delete
wrlocal = ref(self, local_deleted)
[182] Fix | Delete
wrthread = ref(thread, thread_deleted)
[183] Fix | Delete
thread.__dict__[key] = wrlocal
[184] Fix | Delete
self.dicts[idt] = wrthread, localdict
[185] Fix | Delete
return localdict
[186] Fix | Delete
[187] Fix | Delete
[188] Fix | Delete
@contextmanager
[189] Fix | Delete
def _patch(self):
[190] Fix | Delete
impl = object.__getattribute__(self, '_local__impl')
[191] Fix | Delete
try:
[192] Fix | Delete
dct = impl.get_dict()
[193] Fix | Delete
except KeyError:
[194] Fix | Delete
dct = impl.create_dict()
[195] Fix | Delete
args, kw = impl.localargs
[196] Fix | Delete
self.__init__(*args, **kw)
[197] Fix | Delete
with impl.locallock:
[198] Fix | Delete
object.__setattr__(self, '__dict__', dct)
[199] Fix | Delete
yield
[200] Fix | Delete
[201] Fix | Delete
[202] Fix | Delete
class local:
[203] Fix | Delete
__slots__ = '_local__impl', '__dict__'
[204] Fix | Delete
[205] Fix | Delete
def __new__(cls, *args, **kw):
[206] Fix | Delete
if (args or kw) and (cls.__init__ is object.__init__):
[207] Fix | Delete
raise TypeError("Initialization arguments are not supported")
[208] Fix | Delete
self = object.__new__(cls)
[209] Fix | Delete
impl = _localimpl()
[210] Fix | Delete
impl.localargs = (args, kw)
[211] Fix | Delete
impl.locallock = RLock()
[212] Fix | Delete
object.__setattr__(self, '_local__impl', impl)
[213] Fix | Delete
# We need to create the thread dict in anticipation of
[214] Fix | Delete
# __init__ being called, to make sure we don't call it
[215] Fix | Delete
# again ourselves.
[216] Fix | Delete
impl.create_dict()
[217] Fix | Delete
return self
[218] Fix | Delete
[219] Fix | Delete
def __getattribute__(self, name):
[220] Fix | Delete
with _patch(self):
[221] Fix | Delete
return object.__getattribute__(self, name)
[222] Fix | Delete
[223] Fix | Delete
def __setattr__(self, name, value):
[224] Fix | Delete
if name == '__dict__':
[225] Fix | Delete
raise AttributeError(
[226] Fix | Delete
"%r object attribute '__dict__' is read-only"
[227] Fix | Delete
% self.__class__.__name__)
[228] Fix | Delete
with _patch(self):
[229] Fix | Delete
return object.__setattr__(self, name, value)
[230] Fix | Delete
[231] Fix | Delete
def __delattr__(self, name):
[232] Fix | Delete
if name == '__dict__':
[233] Fix | Delete
raise AttributeError(
[234] Fix | Delete
"%r object attribute '__dict__' is read-only"
[235] Fix | Delete
% self.__class__.__name__)
[236] Fix | Delete
with _patch(self):
[237] Fix | Delete
return object.__delattr__(self, name)
[238] Fix | Delete
[239] Fix | Delete
[240] Fix | Delete
from threading import current_thread, RLock
[241] Fix | Delete
[242] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function