• python3-开发进阶Flask的基础(3)


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

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

    一、前奏

    1、一个新名词:偏函数   (可以帮你自动传参数)

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

    2、super和执行类的区别?

    class Base(object):
    
        def func(self):
            print('Base.func')
    
    class Foo(Base):
        def func(self):
            #方式一:根据mro的顺序执行方法  
            # super().func()
            #方式二:主动执行Base类的方法
            # Base.func(self)
            print('Foo.func')
    
    obj=Foo()
    obj.func()
    print(obj.__mro__)

    3、面向对象中特殊方法 setattr/getattr注意事项:

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

    四、栈

    基于列表实现的一个栈:

    class Stack(object):
    
        def __init__(self):
            self.data=[]
    
        def push(self,val):
            self.data.append(val)
    
        def pop(self):
            return self.data.pop()
    
    _stack=Stack()
    _stack.push('大娃')
    _stack.push('二娃')
    
    print(_stack.pop())
    print(_stack.pop())

    5、Local类

    try:
        from greenlet import getcurrent as get_ident   #获取协程的唯一标记
    except:
        from threading import get_ident   #获取线程的唯一标记
    
    class Local(object):
    
        def __init__(self):
            object.__setattr__(self,'storage',{})
    
        def __setattr__(self, key, value):
            ident=get_ident()
            if ident not in self.storage:
                self.storage[ident]={key,value}
            else:
                self.storage[ident][key]=value
    
        def __getattr__(self, item):
            ident=get_ident()
            if ident in self.storage:
                return self.storage[ident].get(item)

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

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

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

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

    6、全局变量只有在初次加载时执行

    二、上下文管理 request

    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中读取数据)

    三、flask-session 

    先下载第三方的库

    pip3 install  flask-session

    用法:

    import redis
    from flask import Flask
    from flask.sessions import SecureCookieSessionInterface
    from flask_session import Session
    
    duo=Flask(__name__)
    
    #duo.session_interface=SecureCookieSessionInterface()
    #duo.session_interface=RedisSessionInterface()
    duo.config['SESSION_TYPE']='redis'
    duo.config['SESSION_TYPE']=redis.Redis(host='11.1.11.1',port=6379,password='123456')
    Session(duo)

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

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

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

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

     

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

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

    总结:

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

    查看源码

    from flask_session import RedisSessionInterface

    四、数据库连接池

    pip3 install DBUtils

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

    import time
    import pymysql
    import threading
    from DBUtils.PooledDB import PooledDB, SharedDBConnection
    POOL = PooledDB(
        creator=pymysql,  # 使用链接数据库的模块
        maxconnections=6,  # 连接池允许的最大连接数,0和None表示不限制连接数
        mincached=2,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
        maxcached=5,  # 链接池中最多闲置的链接,0和None不限制
        maxshared=3,  # 链接池中最多共享的链接数量,0和None表示全部共享。
    PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,
    所以永远是所有链接都共享。
    blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错 maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制 setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."] ping=0, # 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
    host='127.0.0.1', port=3306, user='root', password='123', database='db', charset='utf8' ) def func(): # 检测当前正在运行连接数的是否小于最大链接数,如果不小于则:等待或报raise TooManyConnections异常 # 否则 # 则优先去初始化时创建的链接中获取链接 SteadyDBConnection。 # 然后将SteadyDBConnection对象封装到PooledDedicatedDBConnection中并返回。 # 如果最开始创建的链接没有链接,则去创建一个SteadyDBConnection对象,再封装到PooledDedicatedDBConnection中并返回。 # 一旦关闭链接后,连接就返回到连接池让后续线程继续使用。 conn = POOL.connection() cursor = conn.cursor(pymysql.cursors.DictCursor) #pymsql cursor.execute('select * from tb1') result = cursor.fetchall() conn.close() func()

    注意:

      使用数据库要用连接池

        封装SQLHelper

  • 相关阅读:
    团队管理 - 团队发展五阶段
    信息系统开发平台OpenExpressApp - 支持差异保存
    MDSF:Mendix介绍
    需求入门 - 获取需求方法:Nine Boxes
    个人管理 - 第四代时间管理
    需求入门 - 业务需求分析入门(公司研发峰会演讲ppt)
    个人管理 - Learn More,Study Less!
    如何培养一个人:从育儿谈起
    个人管理 - 如何演讲
    企业架构 - ADM方法概要介绍
  • 原文地址:https://www.cnblogs.com/ManyQian/p/9524074.html
Copyright © 2020-2023  润新知