1. 程式人生 > >flask請求上下文 (轉)

flask請求上下文 (轉)

cbv 返回結果 怎麽 控制臺顯示 查看源 object asc 回到頂部 問題

本篇閱讀目錄

  • 一、flask中的CBV
  • 二、werkzeug + 上下文初步解讀
  • 三、偏函數和線程安全
回到頂部

一、flask中的CBV

  對比django中的CBV,我們來看一下flask中的CBV怎麽實現?

技術分享圖片
  from flask import Flask, render_template, url_for, views

  app = Flask(__name__)

  class Login(views.MethodView):
    def get(self):
      print(url_for("my_login
")) # /login       return render_template("login.html")     def post(self):       return "login success"   app.add_url_rule("/login", view_func=Login.as_view("my_login"))   if __name__ == __main__:     app.run(debug=True)
技術分享圖片

  註意:視圖類中定義了哪些方法,就可以允許哪種方式的請求,也可以通過指定參數methods=["GET","POST"],指定參數時可以在視圖類中指定,也可以在add_url_rule方法中指定。

回到頂部

二、werkzeug + 上下文初步解讀

通過查看源碼,我們知道app.run() 方法其實是執行了run_simple() 方法,源碼如下:

技術分享圖片

  我們可以通過下面一段代碼探究run_simple() 方法都做了什麽?

技術分享圖片
  from werkzeug.serving import run_simple
  from werkzeug.wrappers import Request, Response

  @Request.application
  def app(req):
    print(req.method)    # GET
    print(req.path) # /     return Response(200 ok)   run_simple(0.0.0.0, 5000, app)
技術分享圖片

  運行代碼,發現服務運行在http://0.0.0.0:5000/上,如下:

技術分享圖片

  瀏覽器訪問該網址控制臺顯示的網址,輸出結果如上圖,且頁面顯示返回結果‘200 ok‘。由此說明視圖函數app執行了,再看我們之前寫的代碼:

技術分享圖片
  from flask import Flask, ...

  app = Flask(__name__)

  ......
  
  app.run(debug=True)         # app 是flask的實例化對象
技術分享圖片

  這裏重點分析app.run() 都幹了什麽?

  首先,執行app.run() 時,源碼中顯示執行了執行run_simple() 方法,源碼中run_simple() 方法的參數是run_simple(host, port, self, **options) ,這裏重點看第三個參數self,因為app是flask的實例化對象,因此self就是指flask的實例化對象app,而上例中我們知道當有請求進來的時候,執行了app(),我們知道函數加括號是執行,而對象加括號會自動執行__call__方法,也就是說app.run() 其實是監聽了flask類中的__call__方法,通過解讀源碼我們發現__call__方法內容如下:

技術分享圖片

  __call__方法中執行了wsgi_app方法,源碼如下:

技術分享圖片

  request_context() 方法源碼如下,其中的self仍然是Flask的實例化對象app:

技術分享圖片

  RequestContext是一個類,它的__init__方法源碼如下:

技術分享圖片

  本篇暫時解讀到這裏,下篇繼續解讀。

回到頂部

三、偏函數和線程安全

1、偏函數就是把前邊的值傳進來但是不執行

  1)示例一

技術分享圖片
  from functools import partial

  def ab(a,b):
    print(a,b)   # 1 5
    return a+b

  par_ab = partial(ab, 1)          # par_ab是一個新函數,接受了括號中的參數

  print(par_ab)
  # functools.partial(<function ab at 0x00000203FAB01E18>, 1)

  print(par_ab(5))
  # 6
  # par_ab(5)會執行新函數,且partial(ab, 1)中參數1會成為新函數par_ab的第一個參數,par_ab(5)中的5會成為第二個參數,新函數的函數體是ab函數
技術分享圖片

  2)示例二

技術分享圖片
  from functools import partial

  def ab(a,*args):
    print(a,args)   
    return a

  par_ab = partial(ab, 1, 5, 7, 9)

  print(par_ab)
  # functools.partial(<function ab at 0x0000020396711E18>, 1, 5, 7, 9)
  # 新函數不加括號不執行
技術分享圖片

2、線程安全

  1)示例一:

技術分享圖片
  import time

  class Foo(object):
    pass

  foo = Foo()

  def add(i):
    foo.num = i
    time.sleep(1)
    print(foo.num)

  for i in range(20):
    add(i)
技術分享圖片

    總結:等待時間長

  2)示例二:開啟線程

技術分享圖片
  import time
  import threading

  class Foo(object):
    pass
  
  foo = Foo()

  def add(i):
    foo.num = i
    time.sleep(1)
    print(foo.num, i)

  for i in range(20):
    th = threading.Thread(target=add, args=(i,))
    th.start()
技術分享圖片

    總結:數據不安全

  3)示例三:

技術分享圖片
  import time
  import threading
  from threading import local

  class Foo(local):
    pass

  foo = Foo()

  def add(i):
    foo.num = i
    time.sleep(1)
    print(foo.num, i, threading.current_thread().ident)

  for i in range(20):
    th = threading.Thread(target=add, args=(i,))
    th.start()
技術分享圖片

    總結:完美解決問題,采用了以空間換取時間的方法,為每個線程保存了一塊空間,使線程之間互相不受影響。

轉:https://www.cnblogs.com/li-li/p/10247054.html#autoid-2-0-0

flask請求上下文 (轉)