Flask上下文管理

1、threading-local

一、threding-localhtml

複製代碼
做用:爲每個線程開闢一塊空間進行數據存儲
from threading import local from threading import Thread import time # 示例化local對象 ret=local() def task(s): global ret ret.value=s time.sleep(2) print(ret.value) # 開啓10個線程 for i in range(10): t=Thread(target=task,args=(i,)) t.start()
複製代碼

二、自定義localpython

複製代碼
# 若是有協程則使用協程惟一標識getcurrent
try:
from greenlet import getcurrent as get_ident
except Exception as e:
from threading import Thread,get_ident

class Local(object):
# 線程的惟一標識
ident = get_ident()
def __init__(self):
# 執行父類__setattr__
object.__setattr__(self,"storage",{})

def __setattr__(self,k, v):
"""
構造dict
storage={
ident:{val:0},
ident:{val:1},
ident:{val:3},
ident:{val:4},
}
"""
if self.ident in self.storage:
self.storage[self.ident][k] = v
else:
self.storage[self.ident] = {k: v}

def __getattr__(self,k):

return self.storage[self.ident][k]


obj=Local()

def task(arg):
# 執行__setattr__
obj.var=arg
# 執行__getattr__
v=obj.var
print(v)

for i in range(10):
t = Thread(target=task,args=(i,))
t.start()
複製代碼

2、上下文管理源碼分析

複製代碼
一、上下文管理本質(相似於threading.local)
            一、每個線程都會在Local類中建立一條數據

                  {
                    「惟一標識」:{stark:[ctx,]}
                    「惟一標識」:{stark:[ctx,]}web

                   }面試

            二、當請求進來以後,將請求相關數據添加到列表裏面[request,],之後若是使用時,就去讀取
            三、列表中的數據,請求完成以後,將request從列表中移除
二、在源碼中分析上下文管理
        
        第一階段:執行__call__--->app.wsgi-->將ctx(request,session)封裝爲RequestContent()在(open_session), app_ctx(g,app)封裝爲APPContent()經過LocalStack將這兩個類放入Local對象中
                   
        第二階段:視圖函數導入:request/session/g/app ,經過偏函數(_lookup_req_object)在經過(LocalProxy())去LocalStack中的Local類中對其進行增刪改查操做 

     第三階段:請求處理完畢       
      - 經過save_session將簽名session保存到cookie 
      -經過ctx.pop()去LocalStack中的Local類- 將ctx刪除           
複製代碼

有關面試問題

複製代碼
問題一:flask和django的區別:
  對於django來講,內部組件特別多,自身功能強大,有點大而全,而flask,內置組件不多,可是它的第三方組件不少,擴展性強,有點短小精悍,而它們之間也有類似之處,
  由於它們兩個框架都沒有寫sockte,都是基於wsgi協議作的,在此以外,flask框架中的上下文管理較爲耀眼。

  
  相同點:它們兩個框架都沒有寫sockte,都是基於wsgi協議作的
  請求相關數據傳遞的方式不一樣:django:經過傳遞request參數取值
                flask:見問題二
           組件不一樣:django組件多
                flask組件少,第三方組件豐富

問題1.1: flask上下文管理:
  簡單來講,falsk上下文管理能夠分爲三個階段:
        一、請求進來時,將請求相關的數據放入上下問管理中
        二、在視圖函數中,要去上下文管理中取值
        三、請求響應,要將上下文管理中的數據清除
  
  詳細點來講:
        一、請求剛進來,將request,session封裝在RequestContext類中,app,g封裝在AppContext類中,並經過LocalStack將requestcontext和appcontext放入Local類中
        二、視圖函數中,經過localproxy--->偏函數--->localstack--->local取值
        三、請求相應時,先執行save.session()再各自執行pop(),將local中的數據清除
        

問題1.2 flask第三方組件
  flask:
      -flask-session 默認放入cookie,能夠放入redis
      -flask-redis
      -flask-migrate
      -flask-script
      -blinker 信號
 公共: DBUtils 數據庫鏈接池
      wtforms 表單驗證+生成HTML標籤
      sqlalchemy
  自定義:Auth 參考falsk-login

問題二:Flask中的session是何時建立,何時銷燬的?
  當請求進來時,會將requset和session封裝爲一個RequestContext對象,經過LocalStack將RequestContext放入到Local對象中,由於
請求第一次來session是空值,因此執行open_session,給session(uuid4())賦值,再經過視圖函數處理,請求響應時執行save.session,將簽名session寫入cookie中,再講Local中的數值pop掉。

問題三:flask中一共有幾個LocalStack和Local對象
  兩個LocalStack,兩個Local
  request、session共同用一個LocalStack和Local
  g、app共同用一個Localstack和Local

問題四: 爲何把請求放到RequestContext中:
   由於request和session都是在視圖中操做頻繁的數據,也是用戶請求須要用的數據,將request和session封裝在RequestContext中top,pop一次就能夠完成,而單獨不封裝在一塊兒就會屢次操做,

    ctx = RequestContext(request,session)

問題五:local做用
    -保存 請求上下文對象和app上下文對象

     -localstack的源碼與threading.local(線程處理)做用類似,不一樣之處是Local是經過greenlet(協程)獲取惟一標識,粒度更細redis

      

 問題六:Localstack做用sql

    二、將local對象中的數據維護成一個棧【ctx,ctx】(先進後出)數據庫

         {
            「協程或線程的惟一標識」: { stack:[ctx,ctx,ctx,] }
         }django

    

複製代碼
爲何維護成一個棧?
   當是web應用時:不論是單線程仍是多線程,棧中只有一個數據

   - 服務端單線程:
    {
    111:{stack: [ctx, ]}
    }
   - 服務端多線程:
    {
    111:{stack: [ctx, ]}
    112:{stack: [ctx, ]}
    }flask

離線腳本:能夠在棧中放入多個數據cookie

with app01.app_context():
  print(current_app)
  with app02.app_context():
    print(current_app)
  print(current_app)

複製代碼

 

 問題七:什麼是g?

    g 至關於一次請求的全局變量,當請求進來時將g和current_app封裝爲一個APPContext類,在經過LocalStack將Appcontext放入Local中,取值時經過偏函數,LocalStack、loca l中取值,響應時將local中的g數據刪除:

 問題八:怎麼獲取Session/g/current_app/request

    經過 、偏函數(lookup_req_object)、Localstack、Local取值

 問題九: 技術點:
  - 反射 (LocalProxy())
  - 面向對象,封裝:RequestContext
  - 線程(threading.local)
  - 筆試:本身寫一個類+列表 實現棧。(LocalStack)

問題十:python基本哪些內容比較重要:

一、反射

  -CBV

  -django配置文件

  -wtforms中的Form()示例化中 將"_fields中的數據封裝到From類中"

二、裝飾器 (迭代器,生成器)
  -flask:路由、裝飾器

  -認證

  -csrf

三、面向對象

  -繼承、封裝、多態(簡單描述)

 -雙下劃線:

    __mro__ wtform中 FormMeta中繼承類的優先級

     __dict__    

    __new__ ,實例化可是沒有給當前對象
        wtforms,字段實例化時返回:不是StringField,而是UnboundField

       rest frawork many=Turn  中的序列化

    __call__
       flask 請求的入口app.run()

        字段生成標籤時:字段.__str__ => 字段.__call__ => 插件.__call__

    

       __iter__ 循環對象是,自定義__iter__

        wtforms中BaseForm中循環全部字段時定義了__iter__

    metaclass        - 做用:用於指定當前類使用哪一個類來建立        - 場景:在類建立以前定製操做        示例:wtforms中,對字段進行排序。

相關文章
相關標籤/搜索