一、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()
一、上下文管理本質(相似於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中,對字段進行排序。