thread local in python

thread local in python

参考 Thread Locals in Python: Mostly easy

线程局部变量

1
2
3
4
5
6
7
8
9
10
11
12
import threading

mydata = threading.local()
mydata.x = 'hello'

class Worker(threading.Thread):
def run(self):
mydata.x = self.name
print mydata.x

w1, w2 = Worker(), Worker()
w1.start(); w2.start(); w1.join(); w1.join()
Thread-1
Thread-2

各线程独享自己的变量,但是使用全局变量 mydata

主线程也有自己的线程局部变量

1
2
3
4
5
6
7
8
9
10
11
import threading

mydata = threading.local()
mydata.x = {}

class Worker(threading.Thread):
def run(self):
mydata.x['message'] = self.name
print mydata.x['message']
w1, w2 = Worker(), Worker()
w1.start(); w2.start(); w1.join(); w2.join()
Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python27\lib\threading.py", line 801, in __bootstrap_inner
    self.run()
  File "E:/learn/python/test/thread_local.py", line 15, in run
    mydata.x['message'] = self.name
AttributeError: 'thread._local' object has no attribute 'x'

Exception in thread Thread-2:
Traceback (most recent call last):
  File "C:\Python27\lib\threading.py", line 801, in __bootstrap_inner
    self.run()
  File "E:/learn/python/test/thread_local.py", line 15, in run
    mydata.x['message'] = self.name
AttributeError: 'thread._local' object has no attribute 'x'

线程 w1,w2 没有 x 属性,子线程与主线程拥有各自的变量

继承 threading.local

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import threading

class MyData(threading.local):
def __init__(self):
self.x = {}

mydata = MyData()

class Worker(threading.Thread):
def run(self):
mydata.x['message'] = self.name
print mydata.x['message']

w1, w2 = Worker(), Worker()
w1.start(); w2.start(); w1.join(); w2.join()
Thread-1
Thread-2

应用实例

bottle 0.4.10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Request(threading.local):
""" Represents a single request using thread-local namespace. """

def bind(self, environ):
""" Binds the enviroment of the current request to this request handler """
self._environ = environ
self._GET = None
self._POST = None
self._GETPOST = None
self._COOKIES = None
self.path = self._environ.get('PATH_INFO', '/').strip()
if not self.path.startswith('/'):
self.path = '/' + self.path

#----------------------
request = Request()
#----------------------


def WSGIHandler(environ, start_response):
"""The bottle WSGI-handler."""
global request
global response
request.bind(environ)
response.bind()
try:
handler, args = match_url(request.path, request.method)
if not handler:
raise HTTPError(404, "Not found")
output = handler(**args)
except BreakTheBottle, shard:
output = shard.output

Sync From: https://github.com/TheBigFish/blog/issues/4