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目录下创建 ...
随机推荐
- sublime text快速运行浏览web/html页面
安装View In Browser插件 快捷键 Ctrl+Shift+P(菜单栏Tools->Command Paletter),输入 pcip选中Install Package并回车,输入Vi ...
- Object.keys(),Object.values(),Object.entries()
(1)Object.keys() // 返回数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名. eg:var obj = {a:1,b:'gy'} Ob ...
- 第九篇 AJAX
AJAX 阅读目录(Content) 概述 AJAX常见应用情景 AJAX的优缺点 jQuery实现的AJAX $.ajax参数 AJAX请求如何设置csrf_token 序列化 Django内置的s ...
- webservice 的wsdl文件详解
转 WSDL(Web Service Description Language)Web服务描述语言 ################################################## ...
- 【LeetCode】电话号码的字母组合
[问题]给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合. 给出数字到字母的映射如下(与电话按键相同).注意 1 不对应任何字母. 示例: 输入:" 输出:["ad ...
- unique constraint(PD.HSI_RIGHT) violated
插入时报错,原因:唯一约束重复了.... 查看表中有唯一约束的列是不是已经有值了 果然,唯一约束有两条重复的记录. ------------------------------------------ ...
- Python属性和内建属性
属性property 1. 私有属性添加getter和setter方法 class Money(object): def __init__(self): self.__money = 0 def ge ...
- sql 常用的语句(sql 创建表结构 修改列 清空表)
1.创建表 create Table WorkItemHyperlink ( ID bigint primary key ,--主键 WorkItemID ,) not null,--其中identi ...
- 51Nod-1072-威佐夫游戏
有2堆石子.A B两个人轮流拿,A先拿.每次可以从一堆中取任意个或从2堆中取相同数量的石子,但不可不取.拿到最后1颗石子的人获胜.假设A B都非常聪明,拿石子的过程中不会出现失误.给出2堆石子的数量, ...
- 一行python代码能写出啥?
1.一行代码启动一个Web服务 python -m SimpleHTTPServer 8080 # python2 python3 -m http.server 8080 # python3 2. ...