一。local

  在线程的处理中,常常遇到这样的问题。当一系列线程遇到io操作的时候,就会执行其他线程,这时候就会出现数据冲突,发生数据方面的问题:

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()

  这样的线程是错误的。所以为了区别所有线程,在存储数据的时候往往会加上线程号作为key,取数据的时候也会加上线程号。

from threading import get_ident,Thread
import time
storage = {}
def set(k,v):
ident = get_ident()
if ident in storage:
storage[ident][k] = v
else:
# cxw['线程id']['value']=arg
#storage[1][val]=arg
#storage={1:{val:agr}}
storage[ident] = {k:v} def get(k):
ident = get_ident()
#
#storage = {1: {val: agr}}
return storage[ident][k]
def task(arg):
set('val',arg)
time.sleep(1)
v = get('val')
print(v) for i in range(10):
t = Thread(target=task,args=(i,))
t.start()

函数方式

  这就是local中的内部原理,但是根据类进行封装就需要使用__setattr__,__getattr__,在init中创建存储字典storage防止递归。

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] = v
else:
Local.storage[ident] = {k: v}
def __getattr__(self, k):
ident = get_ident()
return Local.storage[ident][k]
obj = Local()
def task(arg):
#obj.set(val,arg)
obj.val = arg
print(obj.val)
for i in range(10):
t = Thread(target=task,args=(i,))
t.start()

  偏函数

  偏函数就是可以定义任意函数,通过偏函数先定义一部分值,再加上另外的值就可以执行的函数,:

from functools import partial
def test(a,b,c,d):
return a+b+c+d
tes=partial(test,2,2)
print(tes)
print(tes(300,4))
# functools.partial(<function test at 0x00000181D14F1EA0>, 2, 2)
#

二。请求上下文。

  当在全局调用request方法的时候,就可以从其中获取request相关的数据,是在其生成的对象被调用 的时候将request放入。流程如下:

  1.app.__call__

  2.wsgi_app(environ,start_response),将app,环境和请求等信息传入。

  3.ctx = self.request_context(environ),其中是生成一个request对象的函数。此时ctx代表的就是请求对象。

  4.ctx.push(),执行请求对象中的push方法。

  5._request_ctx_stack.push(self)

  这里的_request_ctx_stack,其实就是LocalStack(),所以在这个函数中寻找push方法

  6.push方法

  以上的push方法中需要rv,rv是从_local中获取到,而local其实就是代表线程容器的Local()

  如果没有获得stake就会在其中创建rv,并将该对象添加

  以form为例子,从request中取出该元素,流程如下。

  1.request = LocalProxy(partial(_lookup_req_object, "request"))

  request是licalproxy对象,当点方法从中取东西时,会走__getattr__

  2.getattr,会走_get_current_object

  3._get_current_object

  最终的反射获取的时__init__中的封装方法"_LocalProxy__local"

  而其中的local代表的就是LocalProxy的参数,一个偏函数。

  4.偏函数partial(_lookup_req_object, "request")

  其中的函数走的时_lookup_req_object,最后获取的元素就是top

  5.top

  top代表的就是LocalStack(),所以需要运行其中dtop方法:

  而_local就是Local(),代表线程容器,从中取出刚刚传入的request对象。

'''
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

一些解释

三。蓝图。

  蓝图就是一个项目的框架,可以参照django写一个,

  一个蓝图需要包函以下东西。可以将app下兴建一个pro文件,在这个文件下创建项目相关

  1.manage

  里面放启动的文件和语句,需要导入app

  2.templates 

  在其同一个文件夹下的文件都可以时从其中文件夹下导入模板。

  3.视图

  视图下需要导入app进行修饰。

  4.__init__

  在该文件夹下创建初始化文件,创建app,并导入view,让manage启动时提供view。

  可以看到,不使用蓝图创建框架会使得循环导入,可以从view层的app使用蓝图,将其循环链断开。

  在视图函数中创建蓝图:

us=Blueprint("user",__name__)
@us.route("/")
def index():
return render_template("index.html")

  这样在使用路由后,就可以调用该蓝图。

  当蓝图被创建之后,需要在app下进行注册。

from flask import Flask
app=Flask(__name__)
from pro import views
app.register_blueprint(views.us)

  蓝图中所取的名字,代表每个蓝图的头,可以调用不同蓝图中相同名字 的视图函数,只要前缀添加即可。

  所以,在蓝图中不能出现名字相同的 蓝图

  各个蓝图文件下都有自己的请求扩展周期,执行哪个蓝图就执行哪个蓝图的请求扩展。

  小型flask框架:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint
from flask import render_template
from flask import request account = Blueprint('acc', __name__) @account.route('/login.html', methods=['GET', "POST"])
def login():
return render_template('login.html')

pro_flask/views/account

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint,url_for blog = Blueprint('blog', __name__) @blog.before_request
def a():
print("wo我是blog 的请求扩展") @blog.route("/index")
def index():
print(url_for("acc.login"))
return "ok"

pro_flask/views/blog

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint user = Blueprint('user', __name__)

pro_flask/views/user

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask app = Flask(__name__,template_folder='templates',static_folder='statics',static_url_path='/static') @app.before_request
def a():
print("我是app里面的befor_request") from .views.account import account
from .views.blog import blog
from .views.user import user app.register_blueprint(account)
app.register_blueprint(blog)
app.register_blueprint(user)

pro_flask/__init__

from pro_flask import app

if __name__ == '__main__':
app.run()

run

  url_prefix代表的时这个蓝图的前缀,在前端访问该蓝图下的视图时需要加前缀来区分视图:

  大型flask框架

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint admin = Blueprint(
'admin',
__name__,
template_folder='templates',
static_folder='static'
)
from . import views

pro_flask/admin/__init__

#!/usr/bin/env python
# -*- coding:utf-8 -*- from . import admin @admin.route('/index')
def index():
return 'Admin.Index'

pro_flask/admin/views

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint web = Blueprint(
'web',
__name__,
template_folder='templates',
static_folder='static'
)
from . import views

pro_flask/web/__init__

#!/usr/bin/env python
# -*- coding:utf-8 -*- from . import web @web.route('/index')
def index():
return 'Web.Index'

pro_flask/web/views

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask
from .admin import admin
from .web import web app = Flask(__name__)
app.debug = True app.register_blueprint(admin, url_prefix='/admin')
app.register_blueprint(web)

pro_flask/__init__

from pro_flask import app

if __name__ == '__main__':
app.run()

run

四。g对象

  g对象的特性是,当前请求之内,可以被取出,但是需要先设置,当前请求可以无线取出,和闪现不同的是,这次请求之后,就不再有了,也就是其他请求不能取。

from  flask import Flask,request,g
def set_g():
g.name='nb' @app.route("/index")
def login():
print(g.name)
return ""

  应用场景有可以再请求扩展中,添加判断,给指定路由进行传参。

五。信号

  信号就是当到达某个阶段就会触发某个函数。

  信号需要基于blinker,所以需要安装模块:

pip install blinker

  信号系统自带的有:

  型号的使用:

# 往信号中注册函数
#1给信号绑定要执行的函数
#无需管调用,因为flask,已经给我们设置调用点
def func(*args,**kwargs):
print('触发型号',args,kwargs)
#与该信号进行绑定
signals.request_started.connect(func)
# signals.request_started.send
# 触发信号: signals.request_started.send()

  该信号是再请求扩展之后,view视图之前。

  自定义信号。

  仿照源码,自定义信号需要先创建一个信号对象,再进行绑定,最后使用send进行调用:

  自定义的参数默认传入一个参数,这个参数需要再函数中接受,可以不传,不传值为none,如果需要传其他参数,需要使用关键字参数。

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

  这个模块的作用就是将原本保存cookies的值保存在redis中。

  需要安装模块:

pip install flash-session

  应用如下:

from flask import Flask,session
from flask_session import RedisSessionInterface
import redis
app = Flask(__name__)
app.secret_key="ajksda"
conn=redis.Redis(host='127.0.0.1',port=6379)
#use_signer是否对key签名
app.session_interface=RedisSessionInterface(conn,key_prefix='jason',use_signer=True, permanent=False)
@app.route('/')
def hello_world():
session['nb']='jason'
return 'Hello World!' @app.route("/index")
def index():
print(session['nb'])
return "ok" if __name__ == '__main__':
app.run()

  首先需要调用redis创建一个数据库连接,和密钥

  将app_session_interface接口改成flask-session,其中设置一个前缀。

  保存session时,首先需要将前端返回的session中id获取,将其前缀和id作为redis的name,将其session序列化传入到redis中,并再前端设置一样的value,所以该值和redis中的值是一样的。

  当取值时,通过实现保存到key值,从redis获取到val,再反序列化获得其值。

  session的参数;

  use_signer=True,当这个值为True时,需要设置密钥,否则不需要设置密钥。

  permanent=True,当关闭浏览器时,这个session是否失效。True代表有效,False代表无效。

  简便方法:使用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()

  这个只需要传入存储方式,存储路径,和存储前缀,最后生成Session,就可以完成配置

day91_11_13Local与偏函数的更多相关文章

  1. Python 之匿名函数和偏函数

    匿名函数与偏函数 匿名函数 Python允许使用lambda关键字创造匿名函数,lambda表达式用于定义匿名函数,它返回可调用的函数对象,语法如下: lambda arg1, arg2, … : e ...

  2. python基础——偏函数

    python基础——偏函数 Python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function).要注意,这里的偏函数和数学意义上的偏函数不一样. 在介绍函 ...

  3. Python偏函数

    偏函数 一个带n 个参数,curried 的函数固化第一个参数为固定参数,并返回另一个带n-1 个参数函数对象 >>> from functools import partial & ...

  4. Scala 深入浅出实战经典 第68讲:Scala并发编程原生线程Actor、Cass Class下的消息传递和偏函数实战解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...

  5. Scala 深入浅出实战经典 第67讲:Scala并发编程匿名Actor、消息传递、偏函数解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  6. scala偏函数

    package com.ming.test /** * 在Scala中,偏函数是具有类型PartialFunction[-T,+V]的一种函数.T是其接受的函数类型,V是其返回的结果类型. * 偏函数 ...

  7. Scala中的偏函数与部分应用函数

    Scala中有PartialFunction的概念, 同时还要一个概念叫Partial Applied Function. 前者译作偏函数, 后者译作"偏应用函数"或"部 ...

  8. python 偏函数

    functools.partial可以设置默认参数和关键字参数的默认值 Python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function).要注意,这里的 ...

  9. python偏函数(functool.partail)

    functool.partail 方法可以为一个函数生成偏函数 import functools def f(a,b,c,d): print a,b,c,d a='a' b='b' f1=functo ...

随机推荐

  1. Eureka+SpringBoot2.X结合Security注册中心安全验证

    当我们直接配置完SpringCloudEureka的时候,任何人直接就可以访问,这样是极不安全的!!外网的情况下是绝对不允许的! 好在有提供了解决方案,下面拿为我们提供的Security解决 Spri ...

  2. ASP.NET MVC快速开发框架FastExecutor开发全过程感受及总结

    困境 追溯到2018年5月份,是个炎热的夏天,毕业后1年7个月我提出了离职,原因是受不了原来公司过度的封装框架感觉一年多毫无进步与实施天天轰炸般的电话,偶然间出去面试了一次发现自己知识真的是比较局限, ...

  3. spring+cxf No bean named 'cxf' available

    最近项目中需要用到webservice,在spring中集成cxf时一直报错: 严重: StandardWrapper.Throwable org.springframework.beans.fact ...

  4. git 删除文件/移动文件

    1.git rm 删除文件 git restore --file (git老版本:git checkout) git rm --file(本地和管理都已删除) git rm --cached file ...

  5. pytorch 中改变tensor维度的几种操作

    具体示例如下,注意观察维度的变化 #coding=utf-8 import torch """改变tensor的形状的四种不同变化形式""" ...

  6. Java之Collection接口(单列集合根接口)

    集合概述 集合到底是什么呢?集合:集合是java中提供的一种容器,可以用来存储多个数据 集合和数组既然都是容器,它们有啥区别呢? 区别1: 数组的长度是固定的. 集合的长度是可变的. 区别2:  数组 ...

  7. 剑指Offer-45.扑克牌顺子(C++/Java)

    题目: LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定 ...

  8. LeetCode 3: 无重复字符的最长子串 Longest Substring Without Repeating Characters

    题目: 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. Given a string, find the length of the longest substring withou ...

  9. PHP收集一些常用函数与好用的自定义函数

    .自定义打印函数P //自定义打印function pp($data,$exit=0){// 定义样式 $str='<pre style="display: block;padding ...

  10. ASP.NET webform总结

    一.asp.net中的内置对象1.Page对象属性:isPostBack 回传 返回bool类型通过url访问就是首次加载,通过控件事件访问页面就是回传.二.页面的执行过程 a.每次访问页面,或访问页 ...