python flask 多线程_关于flask线程安全的简单研究

flask是python web开发比较主流的框架之一,也是我在工作中使用的主要开发框架。一直对其是如何保证线程安全的问题比较好奇,所以简单的探究了一番,由于只是简单查看了源码,并未深入细致研究,因此以下内容仅为个人理解,不保证正确性。

首先是很多文章都说flask会为每一个request启动一个线程,每个request都在单独线程中处理,因此保证了线程安全。于是就做了一个简单的测试。首先是写一个简单的flask程序(只需要有最简单的功能用于测试即可),然后我们知道一个flask应用启动之后实际上是作为一个 WSGI application的,之后所有接收到的请求都会经由flask的wsgi_app(self, environ, start_response)方法去处理,所以就来看一下这个方法(注释已去掉)。

defwsgi_app(self, environ, start_response):

ctx=self.request_context(environ)

ctx.push()

error=Nonetry:try:

response=self.full_dispatch_request()exceptException as e:

error=e

response=self.handle_exception(e)returnresponse(environ, start_response)finally:ifself.should_ignore_error(error):

error=None

ctx.auto_pop(error)

那么这个request_context又是什么东西呢?它是一个RequestContext对象,文档是这么说的:

The request context contains all request relevant information. It is

created at the beginning of the request and pushed to the

`_request_ctx_stack` and removed at the end of it. It will create the

URL adapter and request object for the WSGI environment provided.

说的很清楚,这个对象的上下文包含着request相关的信息。也就是说每一个请求到来之后,flask都会为它新建一个RequestContext对象,并且将这个对象push进全局变量_request_ctx_stack中,在push前还要检查_app_ctx_stack,如果_app_ctx_stack的栈顶元素不存在或是与当前的应用不一致,则首先push appcontext 到_app_ctx_stack中,再push requestcontext。源码如下:

defpush(self):

top=_request_ctx_stack.topif top is not None andtop.preserved:

top.pop(top._preserved_exc)#Before we push the request context we have to ensure that there

#is an application context.

app_ctx =_app_ctx_stack.topif app_ctx is None or app_ctx.app !=self.app:

app_ctx=self.app.app_context()

app_ctx.push()

self._implicit_app_ctx_stack.append(app_ctx)else:

self._implicit_app_ctx_stack.append(None)if hasattr(sys, 'exc_clear'):

sys.exc_clear()

_request_ctx_stack.push(self)#Open the session at the moment that the request context is

#available. This allows a custom open_session method to use the

#request context (e.g. code that access database information

#stored on `g` instead of the appcontext).

self.session =self.app.open_session(self.request)if self.session isNone:

self.session= self.app.make_null_session()

通过上面的两步,每一个请求的应用上下文和请求上下文就被push到了全局变量_request_ctx_stack和_app_ctx_stack中。

现在我们知道了_request_ctx_stack和_app_ctx_stack是何时被push的,每一个请求到来都会导致新的RequestContext和AppContext被建立并push,一旦请求处理完毕就被pop出去。而无论是_app_ctx_stack还是_request_ctx_stack都是一个LocalStack对象,这是werkzeug中的一个对象,看看它里边有什么:

classLocalStack(object):def __init__(self):

self._local=Local()def __release_local__

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值