Local与偏函数

threasing.local

  多个线程修改同一个数据,复制多份变量给每个线程用,为每个线程开辟一块空间进行数据存储。

不使用therading.local

  1. # 不用local
  2. from threading import Thread
  3. import time
  4. cxw = -1
  5. def task(arg):
  6. global cxw
  7. cxw = arg
  8. # time.sleep(2)
  9. print(cxw)
  10.  
  11. for i in range(10):
  12. t = Thread(target=task,args=(i,))
  13. t.start()

结果分析:在运行时结果全部显示为9,打印的数据是混乱,当把time.sleep删除后,结果正常打印1,2,3,4....10。

使用threading.local

  1. from threading import Thread
  2. from threading import local
  3. import time
  4. from threading import get_ident
  5. # 特殊的对象
  6. cxw = local()
  7. def task(arg):
  8. # 对象.val = 1/2/3/4/5
  9. cxw.value = arg
  10. time.sleep(2)
  11. print(cxw.value)
  12. for i in range(10):
  13. t = Thread(target=task,args=(i,))
  14. t.start()

  使用local()时数据能正常显示,不混乱。

通过字典自定义threaing.local(函数版)

  1. # 线程下 获取id
  2. from threading import get_ident,Thread
  3. import time
  4. storage = {}
  5. def set(k,v):
  6. index = get_ident()
  7. if index in storage:
  8. storage[index][k] = v
  9. else:
  10. storage[index] = {k:v}
  11. def get(k):
  12. index = get_ident()
  13. return storage[index][k]
  14.  
  15. def task(arg):
  16. set("val",arg)
  17. v = get('val')
  18. print(v)
  19.  
  20. for i in range(10):
  21. t = Thread(target=task,args=(i,))
  22. t.start()

面向对象版

  1. from threading import get_ident,Thread
  2. import time
  3. class Local(object):
  4. storage = {}
  5. def set(self,k,v):
  6. ident = get_ident()
  7. if ident in Local.storage:
  8. Local.storage[ident][k] = v
  9. else:
  10. Local.storage[ident] = {k,v}
  11. def get(self,k):
  12. ident = get_ident()
  13. return Local.storage[ident][k]
  14.  
  15. obj = Local() # 实例化对象
  16. def task(arg):
  17. obj.set('val',arg)
  18. v = obj.get("val")
  19. print(v)
  20.  
  21. for i in range(10):
  22. t = Thread(target=task,args=(i,))
  23. t.start()

通过setattr和getattr实现

  1. # 反射
  2. # hasattr(object,name) # 判断对象是否拥有某个属性
  3. # setattr(object,name,value) #为对象增加新的属性
  4. # getattr(object,name,default) #从对象中获取某个属性
  5. # delattr(object,name) #从对象中删除某个属性
  6. #
  7. from threading import get_ident,Thread
  8. import time
  9. class Local(object):
  10. storage = {}
  11. def __setattr__(self, key, value):
  12. ident = get_ident()
  13. if ident in Local.storage:
  14. Local.storage[ident][key] = value
  15. else:
  16. Local.storage[ident] = {key:value}
  17. def __getattr__(self, key):
  18. ident = get_ident()
  19. return Local.storage[ident][key]
  20. obj = Local()
  21. def task(arg):
  22. obj.val = arg
  23. print(obj.val)
  24. for i in range(10):
  25. t = Thread(target=task,args=(i,))
  26. t.start()

每个对象有自己的存储空间(字典)

  1. from threading import get_ident,Thread
  2. import time
  3. class Local(object):
  4. def __init__(self):
  5. object.__setattr__(self,'storage',{})
  6. self.storage={}
  7. def __setattr__(self, k, v):
  8. ident = get_ident()
  9. if ident in self.storage:
  10. self.storage[ident][k] = v
  11. else:
  12. self.storage[ident] = {k: v}
  13. def __getattr__(self, k):
  14. ident = get_ident()
  15. return self.storage[ident][k]
  16. obj = Local()
  17. def task(arg):
  18. obj.val = arg
  19. obj.xxx = arg
  20. print(obj.val)
  21. for i in range(10):
  22. t = Thread(target=task,args=(i,))
  23. t.start()

兼容线程和协程(源码到request中去看,看local的getattr,setattr)

  1. try:
  2. from greenlet import getcurrent as get_ident
  3. except Exception as e:
  4. from threading import get_ident
  5. from threading import Thread
  6. import time
  7. class Local(object):
  8. def __init__(self):
  9. object.__setattr__(self,'storage',{})
  10. def __setattr__(self, k, v):
  11. ident = get_ident()
  12. if ident in self.storage:
  13. self.storage[ident][k] = v
  14. else:
  15. self.storage[ident] = {k: v}
  16. def __getattr__(self, k):
  17. ident = get_ident()
  18. return self.storage[ident][k]
  19. obj = Local()
  20. def task(arg):
  21. obj.val = arg
  22. obj.xxx = arg
  23. print(obj.val)
  24. for i in range(10):
  25. t = Thread(target=task,args=(i,))
  26. t.start()

  以上的几种Local 实现方法是为了推导出以下源码实现:获取get_ident,setattr和getattr方法的实现。

源码入口:app.__call__>>>wsgi_>>>push>>>Local>>

内部核心源码:

partial偏函数

  1. #偏函数的第二个部分(可变参数),按原有函数的参数顺序进行补充,参数将作用在原函数上,最后偏函数返回一个新函数
  2. from functools import partial
  3. def test(a,b,c,d):
  4. return a+b+c+d
  5.  
  6. tes=partial(test,1,2) # a=1,b=2 c=3,d=4
  7. print(tes(3,4))
    必须遵循传参统一方式,应用场景,传参形式比较随意简便,不必设置默认的变量值。

session源码分析

  1. SecureCookieSessionInterface
  2. -open_session
  3. -save_session

请求上下文

请求步骤源码分析,跳转实现的生命周期。

  1. from flask import Flask,request
  2. app=Flask(__name__)
  3. @app.route("/")
  4. def index():
  5. print(request.form)
  6. return "ok"
  7. if __name__ == '__main__':
  8. #self,是app,app(),--->Flask对象,Flask的__call__
  9. app.__call__
  10. app.run()
  11.  
  12. '''
  13. 1 app.__call__
  14. 2 wsgi_app(environ, start_response)
  15. 2.1 ctx = self.request_context(environ)
  16.  
  17. 2.1.1 return RequestContext(self, environ)
  18. 这里的self是app,environ请求相关
  19. 2.1.2 return RequestContext(self, environ)
  20. 得到了RequestContext的对象,而且有request属性
  21. 2.2 2.1中的ctx就是RequestContext的对象
  22.  
  23. 2.3 ctx.push()执行这个,就是RequestContext的对象的push方法
  24. 2.3.1 #执行这个,self-->ctx
  25. _request_ctx_stack.push(self)
  26. 2.3.1.1 我们发现_request_ctx_stack = LocalStack()
  27. 他的push方法的源码:
  28. def push(self, obj):
  29. rv = getattr(self._local, "stack", None)
  30. if rv is None:
  31. # self._local=>stack-->storage['线程id']['stack']=[ctx,]
  32. self._local.stack = rv = []
  33. rv.append(obj)
  34. return rv
  35.  
  36. 3在请求中获取request.form
  37. 3.1 request是LocalProxy的对象,当获取属性的时候会走__getattr__
  38. def __getattr__(self, name):
  39. if name == "__members__":
  40. return dir(self._get_current_object())
  41. #name-->form,
  42. #self._get_current_object()===>ctx.request,form
  43. #_get_current_object()---》self.__local()
  44.  
  45. return getattr(self._get_current_object(), name)
  46.  
  47. 3.1.1 self._get_current_object():源码:最终:partial(_lookup_req_object, "request")
  48. def _get_current_object(self):
  49.  
  50. if not hasattr(self.__local, "__release_local__"):
  51. #local==>partial(_lookup_req_object, "request")
  52. #def __init__(self, local, name=None):
  53. # object.__setattr__(self, "_LocalProxy__local", local)
  54. #self.__local()===>local()
  55. return self.__local()
  56. try:
  57. return getattr(self.__local, self.__name__)
  58. except AttributeError:
  59. raise RuntimeError("no object bound to %s" % self.__name__)
  60. 4 partial(_lookup_req_object, "request")偏函数的源码
  61. def _lookup_req_object(name):
  62. #name是request
  63. #ctx
  64. top = _request_ctx_stack.top
  65. if top is None:
  66. raise RuntimeError(_request_ctx_err_msg)
  67. #ctx-->request
  68. return getattr(top, name)
  69. 4.1中_request_ctx_stack.top
  70. @property
  71. def top(self):
  72.  
  73. try:
  74. return self._local.stack[-1]
  75. except (AttributeError, IndexError):
  76. return None
  77. '''

截图源码跳转流程:

1:源码入口__call__>>>wsgi_app

2:查看请求方式内,所传的参数信息

3:reruest-context,内需要传的参数信息

4:倒退回来,切入点ctx.push

5:

6:

7:核心部分

8:request请求的方式

蓝图

  对程序进行目录结构划分,类似书籍的目录。

不使用蓝图时,自己分文件,目录结构:

  1. -templates
  2. -views
  3. --__init__.py
  4. -suer.py
  5. -order.py
  6. -app.py

app.py

  1. from views import app
  2. if __name__ == "__main__"
  3. app.run()

__init__.py

  1. from flask import Flask,request
  2. app = Flask(__name__)
  3. # 不导入这个不行
  4.  
  5. from.import account
  6. from.import order
  7. from.import user

user.py

  1. from.import app
  2. @app.route("/user")
  3. def user():
  4. return "user"

order.py

  1. from.import app
  2. @app.route("order")
  3.  
  4. def reder():
  5. return "order"

创建蓝图并注册

推荐使用的两种蓝图模板

  pro_flask_简单应用程序目录示例

创建蓝图

pro_flask_大型应用目录示例

注册蓝图

总结:

1、xxx = Blueprint("account",name,url_prefix="/xxx"):蓝图url前缀,表示url的前缀,表示该蓝图下的所有url都加前缀。

2、xxx = Blueprint("account",name,url_prefix="/xxx",template_folder="tpls"):给当前的蓝图单独使用,向上查找,当找不到,会找总的templates。

3、蓝图的befort_request,对当前蓝图有效。

4、大型项目,可以模拟出类似于django中的多个APP概念。

g对象

  专门用来存储用户信息的对象,g的全称:global,g对象在一次请求中的所有的代码地方,都是可以使用的。

  1. #g对象的特性:
  2. """
  3. 1、当前请求内你设置就可以取,必须先设置,后取,当前请求可以取无限次
  4. 2、就算你当前请求,设置了,如果不取,其他请求过来,也取不到。
  5.  
  6. """
  1. from flask import Flask,g,redirect,request
  2. app = Flask(__name__)
  3. app.debug = True
  4.  
  5. # @app.before_request
  6. # def a():
  7. # if request.path == '/':
  8. # request.name = "hello"
  9. # g.name = "hello"
  10.  
  11. def set_g():
  12. g.name = "hello"
  13.  
  14. @app.route("/")
  15. def index():
  16. set_g()
  17. return redirect("/index")
  18.  
  19. @app.route("/index")
  20. def logon():
  21. print(g.name)
  22. return "ok"

信号

Flask框架中的信号基于blinker,其主要就是让开发者可以在flask请求过程中定制一些用户行为。

安装:

  1. pip3 install blinker

信号的使用

  1. from flask import Flask,signals,render_template
  2.  
  3. app = Flask(__name__)
  4.  
  5. # 往信号中注册函数
  6. #1给信号绑定要执行的函数
  7. #无需管调用,因为flask,已经给我们设置调用点
  8.  
  9. def func(*args,**kwargs):
  10. print('触发型号',args,kwargs)
  11. #与该信号进行绑定
  12. signals.request_started.connect(func)
  13. # signals.request_started.send
  14. # 触发信号: signals.request_started.send()
  15. @app.before_first_request
  16. def before_first1(*args,**kwargs):
  17. print("befor_first_request")
  18.  
  19. @app.before_request
  20. def before_first3(*args,**kwargs):
  21. print("befor_request")
  22.  
  23. @app.route('/',methods=['GET',"POST"])
  24. def index():
  25. print('视图')
  26. return "视图"
  27.  
  28. if __name__ == '__main__':
  29. # app.wsgi_app
  30. app.run()

自定义信号

  绑定+注册

  1. from flask import Flask, current_app, flash, render_template
  2. from flask.signals import _signals
  3.  
  4. app = Flask(import_name=__name__)
  5.  
  6. # 自定义信号
  7. xxxxx = _signals.signal('xxxxx')
  8.  
  9. def func(sender,a):
  10. print(sender,a)
  11. print("我是自定义信号")
  12.  
  13. # 自定义信号中注册函数
  14. xxxxx.connect(func)
  15.  
  16. @app.route("/x")
  17. def index():
  18. # 触发信号
  19. xxxxx.send("sb",a="")
  20. return 'Index'
  21.  
  22. if __name__ == '__main__':
  23. app.run()

flask-session

  作用:将默认保存的签名cookie中的值,保存到redis/meecached/file/mysql/Mongodb等数据库。

安装

  1. pip3 install flask-session

存和取:通过保存在cookie中的key,取出vlaue,到数据库拼接picke序列化,反解出来获取session。

使用

  1. from flask import Flask,session
  2. from flask_session import RedisSessionInterface
  3. import redis
  4. app = Flask(__name__)
  5. app.secret_key="shgihh"
  6. conn=redis.Redis(host='127.0.0.1',port=6379)
  7. #use_signer是否对key签名
  8. app.session_interface=RedisSessionInterface(conn,key_prefix="jack",use_signer=True,permanent=False)
  9. @app.route('/')
  10. def iindex():
  11. session["gook"] = "jack"
  12. return "hello world"
  13.  
  14. @app.route("/index")
  15. def login():
  16. print(session["ok"])
  17. return "full"
  18.  
  19. if __name__ == '__main__':
  20. app.run()

使用2:设置配置,方便更换数据库来保存session数据。

  1. from flask import Flask,session
  2. import redis
  3. from flask_session import Session
  4. app = Flask(__name__)
  5. app.config['SESSION_TYPE'] = 'redis'
  6. app.config['SESSION_REDIS'] =redis.Redis(host='127.0.0.1',port='')
  7. app.config['SESSION_KEY_PREFIX']="jason"
  8. Session(app)
  9.  
  10. @app.route('/')
  11. def hello_world():
  12. session['sb']='jason'
  13. return 'Hello World!'
  14.  
  15. @app.route("/index")
  16. def index():
  17. print(session['sb'])
  18. return "ok"
  19.  
  20. if __name__ == '__main__':
  21. app.run()

flask框架-下的更多相关文章

  1. flask框架下的jinja2模板引擎(2)(过滤器与自定义过滤器)

    flask框架下的jinja2模块引擎(1):https://www.cnblogs.com/chichung/p/9774556.html 这篇论文主要用来记录下 jinja2 的过滤器. 什么是过 ...

  2. flask框架下的jinja2模板引擎(3)(模板继承与可以在模板使用的变量、方法)

    flask 框架下的jinja2模块引擎(1):https://www.cnblogs.com/chichung/p/9774556.html flask 框架下的jinja2模块引擎(2):http ...

  3. flask框架下的jinja2模板引擎(1)(模板渲染)

    #转载请留言联系 模板是什么? 在 flask 框架中,视图函数有两个作用:处理业务逻辑和返回响应内容.在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本.模板作用即是承担视图函 ...

  4. flask框架下读取mysql数据 转换成json格式API

    研究了一天 因为需要从数据库拿数据然后转换成json的格式 expose出去为 API 发现一条数据是容易,两条以上我居然搞了这么久 好歹出来了 先贴一下 后面更新 mysql的操作 比较容易了htt ...

  5. Flask 框架下 Jinja2 模板引擎高层 API 类——Environment

    Environment 类版本: 本文所描述的 Environment 类对应于 Jinja2-2.7 版本.   Environment 类功能: Environment 是 Jinja2 中的一个 ...

  6. 在Python的Flask框架下Address already in use [地址已在使用中]

    出现这种错误提示, 说明你已经有一个流程绑定到默认端口(5000).如果您之前已经运行过相同的模块,则很可能该进程仍然绑定到端口. 首先使用端口窗口查找进程 : sudo  lsof  - i : 5 ...

  7. Python——Flask框架——程序的结构

    一.项目结构 |-flasky |-app Flask程序一般都保存在这里 |-templates/ |-static/ |main/ |-__init__.py |-errors.py |-form ...

  8. flask框架基本使用(3)(session与cookies)

    #转载请留言联系 flask 框架基本使用(1):https://www.cnblogs.com/chichung/p/9756935.html flask 框架基本使用(2):https://www ...

  9. linux下Flask框架搭建简单网页

    开始安装FLASK需要创建一个虚拟环境,虚拟环境可以不干扰正在使用的系统环境,避免影响,并且也不需要完全的root权限,更加安全可靠. 搭建环境 Python3.4 进入到microblog目录下创建 ...

随机推荐

  1. 设置进程用指定IE版本

    function IsWOW64: BOOL; begin Result := False; if GetProcAddress(GetModuleHandle(kernel32), 'IsWow64 ...

  2. Bean XML 配置(3)- 依赖注入配置

    Spring 系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of ...

  3. 第二篇MTV模型、基本命令、简单配置

    MTV模型.基本命令.简单配置 阅读目录(Content) MTV模型 基本命令 简单配置 MTV模型 Django的MTV分别代表: Model(模型):负责业务对象与数据库的对象(ORM) Tem ...

  4. 51NOD1050 循环数组最大字段和

    N个整数组成的循环序列a11,a22,a33,…,ann,求该序列如aii+ai+1i+1+…+ajj的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑an−1n−1,ann,a11, ...

  5. css文本强制两行超出就显示省略号,不显示省略号

    1. 强制一行的情况很简单 overflow:hidden; //超出的隐藏 text-overflow:ellipsis; //省略号 white-space:nowrap; //强制一行显示 2. ...

  6. 10 ~ express ~ 使用 cookie 保存用户 信息

    思维导图: (1) 保存 cookie (2)销毁 cookie 一,保存 cookie 1,app.js  . 新增代码 var Cookies = require('cookies') /** * ...

  7. 通过整合遥感数据和社交媒体数据来进行城市土地利用的分类( Classifying urban land use by integrating remote sensing and social media data)DOI: 10.1080/13658816.2017.1324976 20.0204

    Classifying urban land use by integrating remote sensing and social media data   Xiaoping Liu, Jialv ...

  8. DataRow转实体

    调用                       DataRow row = new DataRow(); ConvertToEntity<实体类>(row) private T Conv ...

  9. linux常用命令之------文件操作、文件查看、权限、打包压缩

    1.一般公司把linux作为自己的应用服务器,将应用和服务器部署在上面 2.测试一般用来打包.压缩.查日志,写一个简单的shell 获得linux服务器的方式 a:网上租一台云服务器 b:安装vmwa ...

  10. GoF 23种设计模式概述

    本文的结构: 一.设计模式总览 二.创建型设计模式 Creational Patterns 三.结构型设计模式 Structural Patterns 四.行为型设计模式 Behavioral Pat ...