threading.local是全局變量可是它的值卻在當前調用它的線程當中spa
在threading module中,有一個很是特別的類local。一旦在主線程實例化了一個local,它會一直活在主線程中,而且又主線程啓動的子線程調用這個local實例時,它的值將會保存在相應的子線程的字典中。能夠爲每一個線程建立一塊獨立的空間,讓他存放數據。線程
在使用threading.local()以前,先了解一下局部變量和全局變量。code
import threading import time def worker(): x = 0 for i in range(100): time.sleep(0.0001) x += 1 print(threading.current_thread(),x) for i in range(10): threading.Thread(target=worker).start() 運行結果: <Thread(Thread-2, started 123145372971008)> 100 <Thread(Thread-6, started 123145393991680)> 100 <Thread(Thread-1, started 123145367715840)> 100 <Thread(Thread-3, started 123145378226176)> 100 <Thread(Thread-5, started 123145388736512)> 100 <Thread(Thread-7, started 123145399246848)> 100 <Thread(Thread-4, started 123145383481344)> 100 <Thread(Thread-10, started 123145415012352)> 100 <Thread(Thread-8, started 123145404502016)> 100 <Thread(Thread-9, started 123145409757184)> 100
全局變量:對象
使用global:blog
import threading import time x = 0 def worker(): global x x = 0 for i in range(100): time.sleep(0.0001) x += 1 print(threading.current_thread(),x) for i in range(10): threading.Thread(target=worker).start() 運行結果: <Thread(Thread-2, started 123145483571200)> 888 <Thread(Thread-5, started 123145499336704)> 908 <Thread(Thread-3, started 123145488826368)> 930 <Thread(Thread-4, started 123145494081536)> 937 <Thread(Thread-1, started 123145478316032)> 941 <Thread(Thread-6, started 123145504591872)> 947 <Thread(Thread-7, started 123145509847040)> 949 <Thread(Thread-8, started 123145515102208)> 955 <Thread(Thread-9, started 123145520357376)> 962 <Thread(Thread-10, started 123145525612544)> 964
上面例子中當主線程中x是全局變量時,就變成了公共資源(也就是同一個對象),每一個子線程互相干擾,最終致使錯誤的計算結果。資源
Python提供了 threading.local 類,將這個類實例化獲得一個全局對象,可是不一樣的線程使用這個對象存儲的數據其它線程不可見(本質上就是不一樣的線程使用這個對象時爲其建立一個獨立的字典)。get
使用threading.local() :it
import threading import time # class A: # def __init__(self,x): # self.x = x # a = A(0) a = threading.local()#全局對象 def worker(): a.x = 0 for i in range(100): time.sleep(0.0001) a.x += 1 print(threading.current_thread(),a.x) for i in range(10): threading.Thread(target=worker).start() 運行結果: <Thread(Thread-4, started 123145570172928)> 100 <Thread(Thread-6, started 123145580683264)> 100 <Thread(Thread-1, started 123145554407424)> 100 <Thread(Thread-2, started 123145559662592)> 100 <Thread(Thread-8, started 123145591193600)> 100 <Thread(Thread-5, started 123145575428096)> 100 <Thread(Thread-3, started 123145564917760)> 100 <Thread(Thread-7, started 123145585938432)> 100 <Thread(Thread-10, started 123145601703936)> 100 <Thread(Thread-9, started 123145596448768)> 100
每一個子線程使用全局對象a,但每一個線程定義的屬性a.x是該線程獨有的。io
舉一個錯誤的例子:,主線程中使用threading.local定義本地變量x,x在主線程中是獨有的,子線程中就訪問不到主線程的x的屬性。ast
import threading X='abc' ctx=threading.local() ctx.x=123 #主線程中定義x本地屬性 print(ctx,type(ctx),ctx.x) def work(): print(X) print(ctx) print(ctx.x) #子線程訪問不到 print('Good job') threading.Thread(target=work).start() 運行結果: <_thread._local object at 0x10407bd00> <class '_thread._local'> 123 abc <_thread._local object at 0x10407bd00> Exception in thread Thread-1: Traceback (most recent call last): File "/Users/ihoney/Python/test_4.py", line 12, in work print(ctx.x) AttributeError: '_thread._local' object has no attribute 'x'
ctx全局對象對主線程和子線程都是能夠使用的,主線程定義了屬性x,但子線程在嘗試訪問屬性x時,就至關於訪問本身線程內的屬性x,而本身線程並無定義,就會拋出AttributeError異常:'_thread._local' object has no attribute 'x'。