import threading local = threading.local()
threading.local
.Класс local()
модуля threading
предоставляет локальные данные потока.
В многопоточном программировании возникают ситуации, когда некоторые ресурсы необходимо необходимо защитить, чтобы они были скрыты от других потоков, которым они не принадлежат. Класс threading.local()
создает объект, способный скрывать значения от просмотра в отдельных потоках.
Локальные данные потока - это данные, значения которых являются специфичными для потока. Чтобы управлять локальными данными потока, просто создайте экземпляр threading.local()
или подкласс и сохраните в нем атрибуты:
Значения экземпляра будут разными для разных потоков.
>>> import threading >>> mydata = threading.local() >>> mydata.x = 1
В примере атрибут local_data.value
не присутствует ни в одном потоке, пока он явно не установлен в этом потоке.
import threading, random def show_value(data): name_thread = threading.current_thread().name try: val = data.value except AttributeError: print(f'{name_thread}: Нет локального значения value') else: print(f'{name_thread}: value={val}') def worker(data): name_thread = threading.current_thread().name show_value(data) print(f'Установка значения value для потока {name_thread}.') data.value = random.randint(1, 100) show_value(data) local_data = threading.local() show_value(local_data) # установка значения value для # основного потока программы local_data.value = 1000 show_value(local_data) for i in range(2): t = threading.Thread(target=worker, args=(local_data,)) t.start() # MainThread: Нет локального значения value # MainThread: value=1000 # Thread-1: Нет локального значения value # Установка значения value для потока Thread-1. # Thread-1: value=63 # Thread-2: Нет локального значения value # Установка значения value для потока Thread-2. # Thread-2: value=35
В некоторых случаях требуется какое-то общее стартовое значение для инициализации потоков программы. Чтобы при старте все потоки получили одного и того же значения, будем использовать подкласс класса threading.local()
, а стартовое значение установим в конструкторе __init__()
.
Для инициализации общего стартового значения для всех потоков, конструктор __init__()
вызывается для одного и того же объекта только один раз в каждом потоке.
import threading, random def show_value(data): name_thread = threading.current_thread().name try: val = data.value except AttributeError: print(f'{name_thread}: Нет локального значения value') else: print(f'{name_thread}: value={val}') def worker(data): name_thread = threading.current_thread().name show_value(data) print(f'{name_thread}: установка локального value') data.value = random.randint(1, 100) show_value(data) class MyLocal(threading.local): # !!! переопределяем конструктор класса def __init__(self, value): super().__init__() self.value = value self.name = threading.current_thread().name print(f'{self.name} стартовое значение {self.value}') local_data = MyLocal(1000) show_value(local_data) for i in range(2): t = threading.Thread(target=worker, args=(local_data,)) t.start() # MainThread стартовое значение 1000 # MainThread: value=1000 # Thread-1 стартовое значение 1000 # Thread-1: value=1000 # Thread-1: установка локального value # Thread-1: value=31 # Thread-2 стартовое значение 1000 # Thread-2: value=1000 # Thread-2: установка локального value # Thread-2: value=69