当前位置: 首页 > news >正文

文登建设局网站建筑考试培训网

文登建设局网站,建筑考试培训网,广州17网,骆驼有没有做网站的公司一、local对象 背景#xff1a; 多线成并发操作一个变量#xff0c;会导致数据错乱#xff0c;可以使用互斥锁加锁处理数据不安全的情况 #xff08;临界区#xff09; 解决#xff1a; 使用local对象处理#xff0c;多个线程操作的变量是local对象#xff0c;就不会…一、local对象 背景 多线成并发操作一个变量会导致数据错乱可以使用互斥锁加锁处理数据不安全的情况 临界区 解决 使用local对象处理多个线程操作的变量是local对象就不会有并发安全的问题。因为它处理了并发安全的问题----请求统一放在一个大字典中key值是线程id号value是个字典。 # {111:{name:jack},222:{name:roma}} llocal() l.namejack----l[111][name] l.nameroma----l[222][name]1.基本使用 不使用local多线程并发操作数据错乱 import time from threading import Thread class Local():passl Local()def task(name):l.name name time.sleep(1)print(在线程内的名字是:, name, l对象中的名字大概率不一样, l.name)if __name__ __main__:for i in range(10):t Thread(targettask, args[jack str(i) 号, ])t.start() # 等待所有线程都执行完成再执行下面代码time.sleep(6)print(l)使用local import time from threading import Thread from threading import local# 定义一个全局变量并发安全的local多个线程操作不会错乱因为每个线程用的都是自己的数据 l local()def task(name):l.name nametime.sleep(1)print(在线程内的名字是, name, l对象中的名字也是, l.name)if __name__ __main__:for i in range(10):t Thread(targettask, args[jack str(i) 号, ])t.start()# 等待所有线程都执行完成再执行下面代码time.sleep(6)print(l)2.自己写一个local类线程和协程并发安全 通过字典自定义threading.local函数 from threading import get_ident,Thread import time storage {} def set(k,v):ident get_ident() # 线程id号if ident in storage:storage[ident][k] velse:storage[ident] {k:v} def get(k):ident get_ident()return storage[ident][k] def task(arg):set(val,arg) #v get(val)print(v)# 10个线程跑完最终storage{123:{val:0},222:{val:1},333:{val:2},444:{val:3}.....} for i in range(10):t Thread(targettask,args(i,))t.start()使用面向对象 from threading import get_ident,Thread import time class Local(object):storage {}def set(self, k, v):ident get_ident()if ident in Local.storage:Local.storage[ident][k] velse:Local.storage[ident] {k: v}def get(self, k):ident get_ident()return Local.storage[ident][k] obj Local() def task(arg):obj.set(val,arg)v obj.get(val)print(v) for i in range(10):t Thread(targettask,args(i,))t.start()通过__setattr__和__getattr__方法实现 from threading import get_ident,Thread import time class Local(object):storage {}def __setattr__(self, k, v):ident get_ident()if ident in Local.storage:Local.storage[ident][k] velse:Local.storage[ident] {k: v}def __getattr__(self, k):ident get_ident()return Local.storage[ident][k] obj Local() def task(arg):obj.val argprint(obj.val) for i in range(10):t Thread(targettask,args(i,))t.start()每个local对象用自己的存储空间字典 from threading import get_ident, Thread import timeclass Local(object):def __init__(self):# self.storage{} # 不能这样写 会递归object.__setattr__(self, storage, {})def __setattr__(self, k, v):ident get_ident() # 获取线程id号if ident in self.storage:self.storage[ident][k] velse:self.storage[ident] {k: v} #def __getattr__(self, k):ident get_ident()return self.storage[ident][k]obj Local()def task(name):obj.name nameprint(obj.name)for i in range(10):t Thread(targettask, args(i,))t.start()兼容线程和协程 try:from greenlet import getcurrent as get_ident except Exception as e:from threading import get_identfrom threading import Thread import time class Local(object):def __init__(self):object.__setattr__(self,storage,{})def __setattr__(self, k, v):ident get_ident()if ident in self.storage:self.storage[ident][k] velse:self.storage[ident] {k: v}def __getattr__(self, k):ident get_ident()return self.storage[ident][k] obj Local() def task(arg):obj.val argobj.xxx argprint(obj.val) for i in range(10):t Thread(targettask,args(i,))t.start()二、flask上下文源码分析 请求上下文执行流程ctx -0 flask项目一启动有6个全局变量-_request_ctx_stackLocalStack对象----封装了local-_app_ctx_stack LocalStack对象-request LocalProxy对象-session LocalProxy对象-1 请求来了 app.__call__()----内部执行self.wsgi_app(environ, start_response)-2 wsgi_app()-2.1 执行ctx self.request_context(environ)返回一个RequestContext对象并且封装了request(当次请求的request对象)session-2.2 执行 ctx.push()RequestContext对象的push方法-2.2.1 push方法中中间位置有_request_ctx_stack.push(self)self是ctx对象-2.2.2 去_request_ctx_stack对象的类中找push方法LocalStack中找push方法-2.2.3 push方法源码def push(self, obj):#通过反射找self._local,在init实例化的时候生成的self._local Local()#Local()flask封装的支持线程和协程的local对象# 一开始取不到stack返回Nonerv getattr(self._local, stack, None)if rv is None:#走到这self._local.stack[],rvself._local.stackself._local.stack rv []# 把ctx放到了列表中#self._local{线程id1:{stack:[ctx,]},线程id2:{stack:[ctx,]},线程id3:{stack:[ctx,]}}rv.append(obj)return rv-3 如果在视图函数中使用request对象比如print(request)-3.1 会调用request对象的__str__方法request类是LocalProxy-3.2 LocalProxy中的__str__方法lambda x: str(x._get_current_object())-3.2.1 内部执行self._get_current_object()-3.2.2 _get_current_object()方法的源码如下def _get_current_object(self):if not hasattr(self.__local, __release_local__):#self.__local() 在init的时候实例化的在init中object.__setattr__(self, _LocalProxy__local, local)# 用了隐藏属性#self.__local 实例化该类的时候传入的local偏函数的内存地址partial(_lookup_req_object, request)#加括号返回就会执行偏函数也就是执行_lookup_req_object不需要传参数了#这个地方的返回值就是request对象(当此请求的request没有乱)return self.__local()try:return getattr(self.__local, self.__name__)except AttributeError:raise RuntimeError(no object bound to %s % self.__name__)-3.2.3 _lookup_req_object函数源码如下def _lookup_req_object(name):#name是request字符串#top方法是把第二步中放入的ctx取出来因为都在一个线程内当前取到的就是当次请求的ctx对象top _request_ctx_stack.topif top is None:raise RuntimeError(_request_ctx_err_msg)#通过反射去ctx中把request对象返回return getattr(top, name)-3.2.4 所以print(request) 实质上是在打印当此请求的request对象的__str__-4 如果在视图函数中使用request对象比如print(request.method):实质上是取到当次请求的reuquest对象的method属性-5 最终请求结束执行 ctx.auto_pop(error)把ctx移除掉其他的东西 -session:-请求来了opensession-ctx.push()----也就是RequestContext类的push方法的最后的地方if self.session is None:#self是ctxctx中有个app就是flask对象 self.app.session_interface也就是它SecureCookieSessionInterface()session_interface self.app.session_interfaceself.session session_interface.open_session(self.app, self.request)if self.session is None:#经过上面还是None的话生成了个空sessionself.session session_interface.make_null_session(self.app)-请求走了savesession-response self.full_dispatch_request() 方法内部执行了before_first_requestbefore_request视图函数after_requestsavesession-self.full_dispatch_request()----执行self.finalize_request(rv)-----》self.process_response(response)----》最后self.session_interface.save_session(self, ctx.session, response)-请求扩展相关before_first_requestbefore_requestafter_request依次执行-信号的触发信号名.send()-flask有一个请求上下文一个应用上下文-ctx:-是RequestContext对象:封装了request和session-调用了_request_ctx_stack.push(self)就是把ctx放到了那个位置-app_ctx:-是AppContext(self) 对象封装了当前的app和g-调用 _app_ctx_stack.push(self) 就是把app_ctx放到了那个位置-g是个什么鬼专门用来存储用户信息的g对象g的全称的为global g对象在一次请求中的所有的代码的地方都是可以使用的(当次请求中传递一些数据)-代理模式-request和session就是代理对象用的就是代理模式-g对象和session的区别g对象只对当次请求有效当此请求内有效session可以跨请求该用户的多次请求中都可以使用总结 1 flask中间件使用请求扩展完成django中间件的功能 2 快速生成当前项目的依赖两种方案 pipreqs 3 函数和方法的区别 面向对象中有方法的概念绑定给对象的绑定给类的方法特殊之处是自动传值方法有可能是函数对象的绑定方法如果类来调用就是函数 4 偏函数 partial 提前给函数传值 5 local对象 解决并发安全的问题多条线程操作同一个变量会出现数据安全问题解决该问题需要加锁每条线程操作的都是自己线程的数据threading包下的local类----实例化得到对象----多线程并发操作----数据不会错乱 6 自定义local对象 self.namelqz # 会触发__setattr__----会出现递归 setattr(self,name,lqz) # 会出现递归 object.__setattr__(self,name,lqz) # 不会出现递归 self.__dict__() # 属性字典也不会出现递归7 flask请求上下文RequestContext----ctx:request,session,flash 8 flask应用上下文AppContext----app_ctx当前appg 9 ctx对象请求上下文flask整个请求的流程 请求来了----app()----触发Flask类的__call__方法----app.wsgi_app()ctx self.request_context(environ) # ctx中包含当此请求的requestsession把ctx放到了local对象中来一个请求就放一次local处理了并发安全所以自己放的都是自己的相互不影响response self.full_dispatch_request()# 执行请求扩展执行视图函数或者视图类处理了session还有信号不管在整个过程中是否出异常ctx都从local对象上移除10 flask请求上下文源码分析 1 请求来了执行----app()----触发类的__call__----self.wsgi_app(environ, start_response)---2 ctx self.request_context(environ)----封装了request和session3 ctx.push()----_request_ctx_stack.push(self)----self是ctx4 _request_ctx_stack是LocalStack类的对象----push 5 LocalStack的push方法源码def push(self, obj):rv getattr(self._local, stack, None)if rv is None:self._local.stack rv []# self._local{线程id1:{stack:[ctx,]},线程id2:{stack:[ctx,]},线程id3:{stack:[ctx,]}}rv.append(obj)return rv6 LocalStack对像中的 _local---init初始化出来的 self._local Local() # 咱们自己写的可以多线程并发访问的Local7 local{线程或协程id号:{stack:[ctx]},线程或协程id号:{stack:[ctx]}} local.stack----取stack的值在不同协程下取到的是自己的8 在视图函数中使用requestsession----都是当此请求的request和session但是我们使用了全局变量。打印的真的是当次请求的Request类的对象但实际上request根本不是Request类的对象LocalProxy类的对象LocalProxy类重写了__str__9 print(request)的时候----类的__str__10 LocalProxy把所有的魔法方法都重写了因为它是个代理类11 request LocalProxy(partial(_lookup_req_object, request)) init----def __init__(self, local, nameNone):----object.__setattr__(self, _LocalProxy__local, local)---local就是偏函数12 LocalProxy---》__str__---_get_current_object()是LocalProxy类的方法13 LocalProxy._get_current_object()---》return self.__local()--》加括号执行偏函数---》partial(_lookup_req_object, request)()---_lookup_req_object(request)14 返回了当前线程所在的ctx中的request对象15 request.method--就是当前线程的request对象的method方法16 在视图函数中打印print(session)---是当此请求的session# 应用上下文 # g到底是什么是一个全局变量放和取在当次请求中的数据# sessionopen_session save_session# 信号的触发位置 # 请求扩展中三个的执行位置
http://www.ho-use.cn/article/10822392.html

相关文章:

  • 网站开发国外研究状况做设计比较好的网站推荐
  • 有网络网站打不开怎么回事wordpress菜单跳转页面跳转
  • 全球最好的黄页网站app 网站开发
  • 建筑网站设计大全网络营销网站源码
  • 线上海报设计网站番禺区保安服务公司
  • 大连网站制作哪家最好学生个人网页设计主题
  • 网站到期续费通知江门论坛建站模板
  • 北京建设工程质量总站网站如何做贷款网站推广
  • 黑群晖建设个人网站深圳2024新冠最新情况
  • php做数据网站网业端云服务
  • 做汽车团购网站html做的网站图片横着摆放
  • 基于wordpress个人博客网站论文做网站视频用哪个视频编辑软件
  • 上海嘉定网站市场营销八大营销模式
  • 汕头网站专业制作外贸网站是什么意思
  • 义乌网站建设优化排名开个网站卖机器怎么做
  • 网站改版提交技术支持 沧州网站建设
  • 男女做那个的网站是什么找做玻璃的网站
  • 东莞市长安网站建设公司jsp做门户网站
  • 简单的app开发制作南昌网站seo
  • 演出票务网站建设福建住房城乡建设部网站
  • wordpress个人博客网站游戏开发软件工具
  • 杭州网站排名服务全国十大网站设计工作室
  • 山东省建设厅举报网站wordpress安装图片不显示不出来
  • 个人做电梯网站网站建设与发布需要什么
  • 荣县规划和建设局网站官方网站建设成果
  • 沧州市做网站如何免费自学网站建设
  • 包小盒设计网站申请免费网站
  • 网站开发 犯法网站开发费用清单
  • 桂林相关网站扬中论坛最新
  • 网页设计国外设计欣赏网站最赚钱的小型加工厂