上篇我们大概简单描述了一下上下文管理,这篇来具体来说说,

  1. 上下管理的request
  2. 上下管理的session
  3. 第三方组件:flask-session
  4. pymysql操作数据库  数据库连接池

 

  1. import functools #装饰器用过的模块
  2.  
  3. def index(a,b):
  4. return a+b
  5. new_fun=functools.partial(index,666) #666当作第一个参数
  6.  
  7. #原来的调用
  8. # ret=index(1,2)
  9. #
  10. # print(ret)
  11. ret=new_fun(1) #偏函数,帮助开发者自动传递参数
  12. print(ret)

 

  1. class Base(object):
  2. def func(self):
  3. print('Base.func')
  4. class Foo(Base):
  5. def func(self):
  6. #方式一:根据mro的顺序执行方法
  7. # super().func()
  8. #方式二:主动执行Base类的方法
  9. # Base.func(self)
  10. print('Foo.func')
  11. obj=Foo()
  12. obj.func()
  13. print(obj.__mro__)

 

  1. class Foo(object):
  2. def __init__(self):
  3. #self.duoduo={} 直接定于会发现调用__setattr__方法时,还没有生成会报错
  4. object.__setattr__(self,'duoduo',{})
  5. def __setattr__(self, key, value):
  6. print(key,value,self.duoduo)
  7. obj=Foo()
  8. print(obj.duoduo)

 

基于列表实现的一个栈:

  1. class Stack(object):
  2. def __init__(self):
  3. self.data=[]
  4. def push(self,val):
  5. self.data.append(val)
  6. def pop(self):
  7. return self.data.pop()
  8. _stack=Stack()
  9. _stack.push('大娃')
  10. _stack.push('二娃')
  11. print(_stack.pop())
  12. print(_stack.pop())

 

  1. try:
  2. from greenlet import getcurrent as get_ident #获取协程的唯一标记
  3. except:
  4. from threading import get_ident #获取线程的唯一标记
  5.  
  6. class Local(object):
  7. def __init__(self):
  8. object.__setattr__(self,'storage',{})
  9. def __setattr__(self, key, value):
  10. ident=get_ident()
  11. if ident not in self.storage:
  12. self.storage[ident]={key,value}
  13. else:
  14. self.storage[ident][key]=value
  15. def __getattr__(self, item):
  16. ident=get_ident()
  17. if ident in self.storage:
  18. return self.storage[ident].get(item)

这个是我们自己写的,我们再去看看flask中的Local类

  1. from flask import globals #点globals
  2. _request_ctx_stack = LocalStack() #点LocalStack()
  3. self._local = Local() #点Local

先看看上面导入的模块:一样的,优先协程,然后线程

 __slots__,只能访问什么属性的范围

 

 

 

1、wsgi   初步处理请求

2 、 __call__方法   执行wsgi_app 

3、ctx=RequestContextsession,request)   再执行  ctx.push()

4、LocalStack对象 把ctx对象添加到local中

5、Local     存数据的时__storage__={‘唯一标识’:{stack:[ctx,]}}

6、视图函数

 

上下文管理:session 

就一个流程,别的基本上一样,

最后通过localstack获取ctx中的session,给session赋值(从cookie中读取数据)

 

先下载第三方的库

  1. pip3 install flask-session

用法:

  1. import redis
  2. from flask import Flask
  3. from flask.sessions import SecureCookieSessionInterface
  4. from flask_session import Session
  5. duo=Flask(__name__)
  6. #duo.session_interface=SecureCookieSessionInterface()
  7. #duo.session_interface=RedisSessionInterface()
  8. duo.config['SESSION_TYPE']='redis'
  9. duo.config['SESSION_TYPE']=redis.Redis(host='11.1.11.1',port=6379,password='123456')
  10. Session(duo)

 

我们来看看Session里面是什么:

app.session_interface赋值,再来看看sef._get_interface(app)

 

这下我们来说说他的原理:

最开始请求进来的时候,这时是根本没有sesiion,找到他的session,执行open_session

 

执行完open_session,就要保存在浏览器上执行save_session

保存好后,下次再来访问:

总结:

  1. session 数据保存到redis   session:随机字符串(每个线程或协程都不一样)
  2. 随机字符串返回给用户

查看源码

  1. from flask_session import RedisSessionInterface

 

  1. pip3 install DBUtils

创建一批连接到连接池,供所有线程共享使用。

  1. import time
  2. import pymysql
  3. import threading
  4. from DBUtils.PooledDB import PooledDB, SharedDBConnection
  5. POOL = PooledDB(
  6. creator=pymysql, # 使用链接数据库的模块
  7. maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制连接数
  8. mincached=2, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
  9. maxcached=5, # 链接池中最多闲置的链接,0和None不限制
  10. maxshared=3, # 链接池中最多共享的链接数量,0和None表示全部共享。
    PS: 无用,因为pymysqlMySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0
    所以永远是所有链接都共享。
  11. blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
  12. maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制
  13. setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
  14. ping=0,
  15. # ping MySQL服务端,检查是否服务可用。
    # 如:0 = None = never, 1 = default = whenever it is requested,
    2 = when a cursor is created, 4 = when a query is executed, 7 = always
  16. host='127.0.0.1',
  17. port=3306,
  18. user='root',
  19. password='123',
  20. database='db',
  21. charset='utf8'
  22. )
  23. def func():
  24. # 检测当前正在运行连接数的是否小于最大链接数,如果不小于则:等待或报raise TooManyConnections异常
  25. # 否则
  26. # 则优先去初始化时创建的链接中获取链接 SteadyDBConnection。
  27. # 然后将SteadyDBConnection对象封装到PooledDedicatedDBConnection中并返回。
  28. # 如果最开始创建的链接没有链接,则去创建一个SteadyDBConnection对象,再封装到PooledDedicatedDBConnection中并返回。
  29. # 一旦关闭链接后,连接就返回到连接池让后续线程继续使用。
  30. conn = POOL.connection()
  31. cursor = conn.cursor(pymysql.cursors.DictCursor) #pymsql
  32. cursor.execute('select * from tb1')
  33. result = cursor.fetchall()
  34. conn.close()
  35. func()

注意:

  使用数据库要用连接池

    封装SQLHelper

版权声明:本文为ManyQian原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/ManyQian/p/9524074.html