本篇阅读目录
一, 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()
总结: 完美解决问题, 采用了以空间换取时间的方法, 为每个线程保存了一块空间, 使线程之间互相不受影响.
转:
来源: http://www.bubuko.com/infodetail-2971512.html