flask框架-下
Local与偏函数
threasing.local
多个线程修改同一个数据,复制多份变量给每个线程用,为每个线程开辟一块空间进行数据存储。
不使用therading.local
- # 不用local
- from threading import Thread
- import time
- cxw = -1
- def task(arg):
- global cxw
- cxw = arg
- # time.sleep(2)
- print(cxw)
- for i in range(10):
- t = Thread(target=task,args=(i,))
- t.start()
结果分析:在运行时结果全部显示为9,打印的数据是混乱,当把time.sleep删除后,结果正常打印1,2,3,4....10。
使用threading.local
- from threading import Thread
- from threading import local
- import time
- from threading import get_ident
- # 特殊的对象
- cxw = local()
- def task(arg):
- # 对象.val = 1/2/3/4/5
- cxw.value = arg
- time.sleep(2)
- print(cxw.value)
- for i in range(10):
- t = Thread(target=task,args=(i,))
- t.start()
使用local()时数据能正常显示,不混乱。
通过字典自定义threaing.local(函数版)
- # 线程下 获取id
- from threading import get_ident,Thread
- import time
- storage = {}
- def set(k,v):
- index = get_ident()
- if index in storage:
- storage[index][k] = v
- else:
- storage[index] = {k:v}
- def get(k):
- index = get_ident()
- return storage[index][k]
- def task(arg):
- set("val",arg)
- v = get('val')
- print(v)
- for i in range(10):
- t = Thread(target=task,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] = v
- else:
- 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(target=task,args=(i,))
- t.start()
通过setattr和getattr实现
- # 反射
- # hasattr(object,name) # 判断对象是否拥有某个属性
- # setattr(object,name,value) #为对象增加新的属性
- # getattr(object,name,default) #从对象中获取某个属性
- # delattr(object,name) #从对象中删除某个属性
- #
- from threading import get_ident,Thread
- import time
- class Local(object):
- storage = {}
- def __setattr__(self, key, value):
- ident = get_ident()
- if ident in Local.storage:
- Local.storage[ident][key] = value
- else:
- Local.storage[ident] = {key:value}
- def __getattr__(self, key):
- ident = get_ident()
- return Local.storage[ident][key]
- obj = Local()
- def task(arg):
- obj.val = arg
- print(obj.val)
- for i in range(10):
- t = Thread(target=task,args=(i,))
- t.start()
每个对象有自己的存储空间(字典)
- from threading import get_ident,Thread
- import time
- class Local(object):
- def __init__(self):
- object.__setattr__(self,'storage',{})
- self.storage={}
- def __setattr__(self, k, v):
- ident = get_ident()
- if ident in self.storage:
- self.storage[ident][k] = v
- else:
- self.storage[ident] = {k: v}
- def __getattr__(self, k):
- ident = get_ident()
- return self.storage[ident][k]
- obj = Local()
- def task(arg):
- obj.val = arg
- obj.xxx = arg
- print(obj.val)
- for i in range(10):
- t = Thread(target=task,args=(i,))
- t.start()
兼容线程和协程(源码到request中去看,看local的getattr,setattr)
- try:
- from greenlet import getcurrent as get_ident
- except Exception as e:
- from threading import get_ident
- from 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] = v
- else:
- self.storage[ident] = {k: v}
- def __getattr__(self, k):
- ident = get_ident()
- return self.storage[ident][k]
- obj = Local()
- def task(arg):
- obj.val = arg
- obj.xxx = arg
- print(obj.val)
- for i in range(10):
- t = Thread(target=task,args=(i,))
- t.start()
以上的几种Local 实现方法是为了推导出以下源码实现:获取get_ident,setattr和getattr方法的实现。
源码入口:app.__call__>>>wsgi_>>>push>>>Local>>
内部核心源码:
partial偏函数
- #偏函数的第二个部分(可变参数),按原有函数的参数顺序进行补充,参数将作用在原函数上,最后偏函数返回一个新函数
- from functools import partial
- def test(a,b,c,d):
- return a+b+c+d
- tes=partial(test,1,2) # a=1,b=2 c=3,d=4
- print(tes(3,4))
必须遵循传参统一方式,应用场景,传参形式比较随意简便,不必设置默认的变量值。
session源码分析
- SecureCookieSessionInterface
- -open_session
- -save_session
请求上下文
请求步骤源码分析,跳转实现的生命周期。
- from flask import Flask,request
- app=Flask(__name__)
- @app.route("/")
- def index():
- print(request.form)
- return "ok"
- if __name__ == '__main__':
- #self,是app,app(),--->Flask对象,Flask的__call__
- app.__call__
- app.run()
- '''
- 1 app.__call__
- 2 wsgi_app(environ, start_response)
- 2.1 ctx = self.request_context(environ)
- 2.1.1 return RequestContext(self, environ)
- 这里的self是app,environ请求相关
- 2.1.2 return RequestContext(self, environ)
- 得到了RequestContext的对象,而且有request属性
- 2.2 2.1中的ctx就是RequestContext的对象
- 2.3 ctx.push()执行这个,就是RequestContext的对象的push方法
- 2.3.1 #执行这个,self-->ctx
- _request_ctx_stack.push(self)
- 2.3.1.1 我们发现_request_ctx_stack = LocalStack()
- 他的push方法的源码:
- def push(self, obj):
- rv = getattr(self._local, "stack", None)
- if rv is None:
- # self._local=>stack-->storage['线程id']['stack']=[ctx,]
- self._local.stack = rv = []
- rv.append(obj)
- return rv
- 3在请求中获取request.form
- 3.1 request是LocalProxy的对象,当获取属性的时候会走__getattr__
- def __getattr__(self, name):
- if name == "__members__":
- return dir(self._get_current_object())
- #name-->form,
- #self._get_current_object()===>ctx.request,form
- #_get_current_object()---》self.__local()
- return getattr(self._get_current_object(), name)
- 3.1.1 self._get_current_object():源码:最终:partial(_lookup_req_object, "request")
- def _get_current_object(self):
- if not hasattr(self.__local, "__release_local__"):
- #local==>partial(_lookup_req_object, "request")
- #def __init__(self, local, name=None):
- # object.__setattr__(self, "_LocalProxy__local", local)
- #self.__local()===>local()
- return self.__local()
- try:
- return getattr(self.__local, self.__name__)
- except AttributeError:
- raise RuntimeError("no object bound to %s" % self.__name__)
- 4 partial(_lookup_req_object, "request")偏函数的源码
- def _lookup_req_object(name):
- #name是request
- #ctx
- top = _request_ctx_stack.top
- if top is None:
- raise RuntimeError(_request_ctx_err_msg)
- #ctx-->request
- return getattr(top, name)
- 4.1中_request_ctx_stack.top
- @property
- def top(self):
- try:
- return self._local.stack[-1]
- except (AttributeError, IndexError):
- return None
- '''
截图源码跳转流程:
1:源码入口__call__>>>wsgi_app
2:查看请求方式内,所传的参数信息
3:reruest-context,内需要传的参数信息
4:倒退回来,切入点ctx.push
5:
6:
7:核心部分
8:request请求的方式
蓝图
对程序进行目录结构划分,类似书籍的目录。
不使用蓝图时,自己分文件,目录结构:
- -templates
- -views
- --__init__.py
- -suer.py
- -order.py
- -app.py
app.py
- from views import app
- if __name__ == "__main__"
- app.run()
__init__.py
- from flask import Flask,request
- app = Flask(__name__)
- # 不导入这个不行
- from.import account
- from.import order
- from.import user
user.py
- from.import app
- @app.route("/user")
- def user():
- return "user"
order.py
- from.import app
- @app.route("order")
- def reder():
- 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对象在一次请求中的所有的代码地方,都是可以使用的。
- #g对象的特性:
- """
- 1、当前请求内你设置就可以取,必须先设置,后取,当前请求可以取无限次
- 2、就算你当前请求,设置了,如果不取,其他请求过来,也取不到。
- """
- from flask import Flask,g,redirect,request
- app = Flask(__name__)
- app.debug = True
- # @app.before_request
- # def a():
- # if request.path == '/':
- # request.name = "hello"
- # g.name = "hello"
- def set_g():
- g.name = "hello"
- @app.route("/")
- def index():
- set_g()
- return redirect("/index")
- @app.route("/index")
- def logon():
- print(g.name)
- return "ok"
信号
Flask框架中的信号基于blinker,其主要就是让开发者可以在flask请求过程中定制一些用户行为。
安装:
- pip3 install blinker
信号的使用
- from flask import Flask,signals,render_template
- app = Flask(__name__)
- # 往信号中注册函数
- #1给信号绑定要执行的函数
- #无需管调用,因为flask,已经给我们设置调用点
- def func(*args,**kwargs):
- print('触发型号',args,kwargs)
- #与该信号进行绑定
- signals.request_started.connect(func)
- # signals.request_started.send
- # 触发信号: signals.request_started.send()
- @app.before_first_request
- def before_first1(*args,**kwargs):
- print("befor_first_request")
- @app.before_request
- def before_first3(*args,**kwargs):
- print("befor_request")
- @app.route('/',methods=['GET',"POST"])
- def index():
- print('视图')
- return "视图"
- if __name__ == '__main__':
- # app.wsgi_app
- app.run()
自定义信号
绑定+注册
- from flask import Flask, current_app, flash, render_template
- from flask.signals import _signals
- app = Flask(import_name=__name__)
- # 自定义信号
- xxxxx = _signals.signal('xxxxx')
- def func(sender,a):
- print(sender,a)
- print("我是自定义信号")
- # 自定义信号中注册函数
- xxxxx.connect(func)
- @app.route("/x")
- def index():
- # 触发信号
- xxxxx.send("sb",a="")
- return 'Index'
- if __name__ == '__main__':
- app.run()
flask-session
作用:将默认保存的签名cookie中的值,保存到redis/meecached/file/mysql/Mongodb等数据库。
安装
- pip3 install flask-session
存和取:通过保存在cookie中的key,取出vlaue,到数据库拼接picke序列化,反解出来获取session。
使用
- from flask import Flask,session
- from flask_session import RedisSessionInterface
- import redis
- app = Flask(__name__)
- app.secret_key="shgihh"
- conn=redis.Redis(host='127.0.0.1',port=6379)
- #use_signer是否对key签名
- app.session_interface=RedisSessionInterface(conn,key_prefix="jack",use_signer=True,permanent=False)
- @app.route('/')
- def iindex():
- session["gook"] = "jack"
- return "hello world"
- @app.route("/index")
- def login():
- print(session["ok"])
- return "full"
- if __name__ == '__main__':
- app.run()
使用2:设置配置,方便更换数据库来保存session数据。
- from flask import Flask,session
- import redis
- from flask_session import Session
- app = Flask(__name__)
- app.config['SESSION_TYPE'] = 'redis'
- app.config['SESSION_REDIS'] =redis.Redis(host='127.0.0.1',port='')
- app.config['SESSION_KEY_PREFIX']="jason"
- Session(app)
- @app.route('/')
- def hello_world():
- session['sb']='jason'
- return 'Hello World!'
- @app.route("/index")
- def index():
- print(session['sb'])
- return "ok"
- if __name__ == '__main__':
- app.run()
flask框架-下的更多相关文章
- flask框架下的jinja2模板引擎(2)(过滤器与自定义过滤器)
flask框架下的jinja2模块引擎(1):https://www.cnblogs.com/chichung/p/9774556.html 这篇论文主要用来记录下 jinja2 的过滤器. 什么是过 ...
- flask框架下的jinja2模板引擎(3)(模板继承与可以在模板使用的变量、方法)
flask 框架下的jinja2模块引擎(1):https://www.cnblogs.com/chichung/p/9774556.html flask 框架下的jinja2模块引擎(2):http ...
- flask框架下的jinja2模板引擎(1)(模板渲染)
#转载请留言联系 模板是什么? 在 flask 框架中,视图函数有两个作用:处理业务逻辑和返回响应内容.在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本.模板作用即是承担视图函 ...
- flask框架下读取mysql数据 转换成json格式API
研究了一天 因为需要从数据库拿数据然后转换成json的格式 expose出去为 API 发现一条数据是容易,两条以上我居然搞了这么久 好歹出来了 先贴一下 后面更新 mysql的操作 比较容易了htt ...
- Flask 框架下 Jinja2 模板引擎高层 API 类——Environment
Environment 类版本: 本文所描述的 Environment 类对应于 Jinja2-2.7 版本. Environment 类功能: Environment 是 Jinja2 中的一个 ...
- 在Python的Flask框架下Address already in use [地址已在使用中]
出现这种错误提示, 说明你已经有一个流程绑定到默认端口(5000).如果您之前已经运行过相同的模块,则很可能该进程仍然绑定到端口. 首先使用端口窗口查找进程 : sudo lsof - i : 5 ...
- Python——Flask框架——程序的结构
一.项目结构 |-flasky |-app Flask程序一般都保存在这里 |-templates/ |-static/ |main/ |-__init__.py |-errors.py |-form ...
- flask框架基本使用(3)(session与cookies)
#转载请留言联系 flask 框架基本使用(1):https://www.cnblogs.com/chichung/p/9756935.html flask 框架基本使用(2):https://www ...
- linux下Flask框架搭建简单网页
开始安装FLASK需要创建一个虚拟环境,虚拟环境可以不干扰正在使用的系统环境,避免影响,并且也不需要完全的root权限,更加安全可靠. 搭建环境 Python3.4 进入到microblog目录下创建 ...
随机推荐
- 设置进程用指定IE版本
function IsWOW64: BOOL; begin Result := False; if GetProcAddress(GetModuleHandle(kernel32), 'IsWow64 ...
- Bean XML 配置(3)- 依赖注入配置
Spring 系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of ...
- 第二篇MTV模型、基本命令、简单配置
MTV模型.基本命令.简单配置 阅读目录(Content) MTV模型 基本命令 简单配置 MTV模型 Django的MTV分别代表: Model(模型):负责业务对象与数据库的对象(ORM) Tem ...
- 51NOD1050 循环数组最大字段和
N个整数组成的循环序列a11,a22,a33,…,ann,求该序列如aii+ai+1i+1+…+ajj的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑an−1n−1,ann,a11, ...
- css文本强制两行超出就显示省略号,不显示省略号
1. 强制一行的情况很简单 overflow:hidden; //超出的隐藏 text-overflow:ellipsis; //省略号 white-space:nowrap; //强制一行显示 2. ...
- 10 ~ express ~ 使用 cookie 保存用户 信息
思维导图: (1) 保存 cookie (2)销毁 cookie 一,保存 cookie 1,app.js . 新增代码 var Cookies = require('cookies') /** * ...
- 通过整合遥感数据和社交媒体数据来进行城市土地利用的分类( 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 ...
- DataRow转实体
调用 DataRow row = new DataRow(); ConvertToEntity<实体类>(row) private T Conv ...
- linux常用命令之------文件操作、文件查看、权限、打包压缩
1.一般公司把linux作为自己的应用服务器,将应用和服务器部署在上面 2.测试一般用来打包.压缩.查日志,写一个简单的shell 获得linux服务器的方式 a:网上租一台云服务器 b:安装vmwa ...
- GoF 23种设计模式概述
本文的结构: 一.设计模式总览 二.创建型设计模式 Creational Patterns 三.结构型设计模式 Structural Patterns 四.行为型设计模式 Behavioral Pat ...