为什么使用werkzeug.Local而不是threading.local,因为python中应用基于协程运行,使用thread local变量可能会造成请求间数据相互干扰,因为一个线程中存在多个请求。
Werkzeug 的设计者认为python自带的ThreadLocal并不能满足需求,主要因为下面两个原因:
- Werkzeug 主要用“ThreadLocal”来满足并发的要求,python 自带的ThreadLocal只能实现基于线程的并发。而python中还有其他许多并发方式,比如常见的协程(greenlet),因此需要实现一种能够支持协程的Local对象。
- WSGI不保证每次都会产生一个新的线程来处理请求,也就是说线程是可以复用的(可以维护一个线程池来处理请求)。这样如果werkzeug 使用python自带的ThreadLocal,一个“不干净(存有之前处理过的请求的相关数据)”的线程会被用来处理新的请求。
在Django中的应用
想要获取requst对象,但是不在views函数里
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Description: thread locals middleware
# Create: 2008-6-4
try:
from threading import local
except ImportError:
from django.utils._threading_local import local
_thread_locals = local()
def get_current_user():
return getattr(_thread_locals, 'user', None)
class ThreadLocals(object):
"""Middleware that gets various objects from the
request object and saves them in thread local storage."""
def process_request(self, request):
_thread_locals.user = getattr(request, 'user', None)
MIDDLEWARE_CLASSES = (
"django.middleware.common.CommonMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"yourproject.middleware.threadlocals.ThreadLocals",
)
from net4.middleware import threadlocals
def save(self):
if self.id is None:
self.author = threadlocals.get_current_user()
super(Post, self).save()