的为主组织,学习笔记

By admin in 4858.com on 2019年4月7日

python 3.x

Flask开撸,flask

python 3.x

安装 Flask

pip install Flask

 

 

from flask import Flask app = Flask(__name__)
  @app.route(“/”) #
take note of this decorator syntax, it’s a common
pattern
def hello():     return “Hello
World!”   if __name__ == “__main__”:
    app.run()

python 3.x 安装 Flask pip
install Flask from flask import Flask app = Flask ( __name__ ) @ app
. route ( “/” ) # take note of this decorator syntax, it’s a
co…

上下文那些定义多见于文章中,是一句话中的语境,也正是言语环境。一句莫名其妙的话现身会令人不掌握什么看头,就算有语言环境的认证,则会更好,那正是语境对语意的震慑。
上下文是1种属性的雷打不动系列,为驻留在环境内的靶子定义环境。在指标的激活进度中创造上下文,对象被陈设为供给某个活动服务,如一道、事务、实时激活、安全性等等。

初始化

享有 Flask 程序都不能不创立多个 app 实例。Web 服务器使用 Web
服务器网关接口协议(Web Server Gateway Interface,
WSGI)把收到自客户端的兼具请求都传送给那么些对象拍卖。 app 实例是 Flask
类的对象:

from flask import Flask
app = Flask(__name__)

Flask 类的构造函数自有三个务必内定的参数, 即 app 主模块或包的名字。

Flask 用 name 那个参数决定程序的根目录,
以便稍后能够找到相对于程序根目录的资源文本位置。

安装 Flask

比如在处理器中,相对于经过而言,上下文就是进度执行时的条件。具体来说正是各样变量和数目,包括富有的寄存器变量、进程打开的文本、内部存款和储蓄器新闻等。能够了然上下文是条件的叁个快速照相,是1个用于保存境况的指标。在先后中大家所写的函数大都不是独立完整的,在利用1个函数落成本身效益的时候,很或者须要同其它的片段进行交互,供给其它外部环境变量的支撑,上下文便是给外部环境的变量赋值,使函数能正确运维。

路由和视图函数

客户端(例如 Web 浏览器)把请求发送给 Web 服务器, Web
服务器再把请求发送给 Flask app 实例。 app 实例须求明白对各种 UBMWX3L
请求运营哪些代码, 所以 app 实例保存了3个 U宝马X3L 到 Python
函数的炫耀关系。处理 UHavalL 和函数之间涉及的次序名叫路由。

在 Flask 中行使 app 实例提供的 app.route
装饰器把所装修的函数注册为路由:

@app.route('/')
def index():
    return '<h1>Hello, 世界!</h1>'

装饰器是能够把函数注册为事件的处理程序。

伊始是把 index() 函数注册为 app
根地址的处理程序。若是安排的次第的服务器域名字为
www.example.com,
在浏览器中访问
http://www.example.com
后会接触服务器执行 index() 函数。那几个函数的回来值称为 响应,
它是客户端接收到的情节。假设客户端是 Web 浏览器,
响应正是体现给用户看的文书档案。

像 index() 那样的函数称之为 视图函数(view
function)。视图函数再次回到的响应得以是包蕴 HTML
的简易字符串,也得以是纵横交叉的表单。

可变 URL:

@app.route('/user/<name>')
def user(name):
    return '<h1>Hello, %s!</h1>' % name

路由中的动态部分私下认可使用字符串, 也足以动用 int/float/path 类型, path
类型也是字符串, 但不把斜线作为分割符, 而将其视作动态片段的一片段。

@app.route('/user/<int:id>')

pip install Flask

Flask提供了三种上下文,一种是利用上下文(Application
Context),一种是请求上下文(Request Context)。
能够查看Flask的文书档案:使用上下文
呼吁上下文

起步服务器

app 实例使用 run 方法运转 Flask 集成的 Web 服务器:

if __name__ == '__main__':
    app.run(debug=True)

__name__ == '__main__' 确定保证了唯有直接 执行这么些本牛时才起步 Web
服务器。假诺这几个剧本由别的脚本引进, 程序假定父级脚本会运营分裂的服务器,
由此不会执行 app.run()

服务器运转后会进入轮询, 等待并处理请求,
轮询会一向运转,直到程序停止,例如按 Ctrl-C 键。

 

的为主组织,学习笔记。深刻浅出地解释一下application contextrequest context

2个完好的 app

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return '<h1>Hello, 世界!</h1>'

@app.route('user/<name>')
def user(name):
    return '<h1>hello, %s!</h1>' % name

if __name__ == '__main__':
    app.run(debug=True)

运维那几个 app:

(venv) $ python hello.py
* Running on http://127.0.0.1:5000/
* Restarting with reloader

在浏览器中键入:

 http://localhost:5000/user/Dave

会显示:

<h1>Hello, Dave!</h1>


 

  1. application 指的正是当您调用app =
    Flask(name)创立的那个指标app;

恳请/响应循环

from flask import Flask

  1. request 指的是历次http请求产生时,WSGI
    server(比如gunicorn)调Flask.call()之后,在Flask对象内部创建的Request对象;
  2. application 表示用于响应WSGI请求的利用自身,request
    表示每一遍http请求;
  3. application的生命周期大于request,一个application幸存时期,恐怕发生频仍http请求,所以,也就会有几个request

app 和呼吁上下文

Flask 从客户端收到请求时, 要让视图函数能访问片段对象,
那样才能处理请求。请求对象包装了客户端(例如浏览器)发送的 HTTP 请求。

要让视图函数能访问呼吁对象
二个斐然的艺术是把请求对象作为参数字传送递给视图函数,
不过那会造成程序中种种视图函数都增多二个参数。如果视图函数还要访问别的对象,
那么视图函数会变得更为臃肿和难以保证。

为此, Flask 使用 上下文 一时把有些对象变成全局可访问:

from flask import request
@app.route('/')
def index():
    user_agent = request.headers.get('User-Agent')
    return '<p>你的浏览器是 %s</p>' % user_agent

在这些事例中我们把 request 当作全局变量来利用。事实上, request
不只怕是全局变量, 你牵记,
在四个线程同时处理不一致客户端发送的两样请求时, 每一个线程看到的 request
对象自然分裂。 Flask 使用上下文让特定的变量在每3个线程中全局可访问,
与此同时却不会搅乱其余线程。

四线程 Web 服务器会创立一个线程池,
再从线程池中选拔叁个线程用于拍卖接收到的伸手。

在 Flask 中有二种上下文: app 上下文
请求上下文。下表列出了那三种上下文提供的全局变量:

变量名 上下文 说明
current_app app上下文 当前所激活app的app实例
g app上下文 处理请求时用作临时存储的对象。每次请求都会重设这个变量
request 请求上下文 请求对象, 封装了客户端发出的 HTTP 请求中的内容
session 请求上下文 用户会话, 用于存储请求之间需要"记住"的值的字典

Flask 在散发请求从前激活(或推送)app上下文和乞求上下文,
请求处理达成后再将其删除。 app 上下文在被推送后, 就足以在线程中选取
current_appg 变量。类似地, 在伸手上下文被推送后, 就足以采取
requestsession 变量。假如大家使用那几个变量时未尝激活 app
上下文或请求上下文, 那么程序就会出错。

激活虚拟环境后进入 Python shell, 上面演示app上下文的选用形式:

>>> from hello import app
>>> from flask import current_app
>>> current_app.name
...
RuntimeError: Working outside of application context.
>>> app_ctx = app.app_context()
>>> app_ctx.push() # 推送 app 上下文
>>> current_app.name
'hello'
>>> app_ctx.pop() # 弹出 app 上下文

在那些事例中, 未有激活 app 上下文在此以前就调用 current_app.name
就会招致错误, 可是推送完上下文之后就可以调用了。

留神, 在 app 实例上调用 .app_context() 方法便获得了几个主次上下文。

app = Flask(__name__)


恳申请调离度

先后收到客户端发来的恳求时, 要找随处理该请求的视图函数。Flask 通过在 app
的 U君越L 映射中查找请求的 U福睿斯L 来成功那么些职务。 UEscortL 映射是 U奥迪Q伍L
和视图函数之间的照应关系。 Flask 使用 app.route 装饰器/非装饰器格局的
app.add_url_rule() 生成映射。

大家在 Python shell 中查阅 Flask 的 app
中映射是什么体统的:(全数操作请保管您早已激活了虚拟环境)

(venv) $ python
>>> from hello import app
>>> app.url_map
>>> app.url_map
Map([<Rule '/' (HEAD, OPTIONS, GET) -> index>,
<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
<Rule '/user/<name>' (HEAD, OPTIONS, GET) -> user>])

//usr/<name> 路由在 app 中使用 app.route 装饰器定义。
/static/<filename> 路由是 Flask 添加的特种路由, 用于访问静态文件。

ULANDL 映射中的 HEAD、OPTIONS、GET 是呼吁方法。Flask
为各种路由都钦命了请求方法, 那样不一样的乞求发送到相同的 U卡宴L 上时,
会使用不一样的视图函数进行处理。 HEAD 和 OPTIONS 方法由 Flask 自动处理,
由此能够说地点的 app 中 UQashqaiL 映射中的 叁 个路由都选拔 GET 方法。

 

请求上下文

from flask import request
@app.route('/')
def index():
    user_agent = request.headers.get('User-Agent')
    return '<p>Your browser is %s</p>' % user_agent```

Flask中有多种请求hook,分别是@before_first_request @before_request
@after_request @teardown_request

宛如上边的代码一样,在每一种请求上下文的函数中大家都足以访问request对象,但是request对象却并不是大局的,因为当大家无论声可瑞康(Karicare)个函数的时候,比如:

def handle_request():
    print 'handle request'
    print request.url 
if __name__=='__main__':
    handle_request()

那时运作就会发生

RuntimeError: working outside of request context。

因而可以,Flask的request对象唯有在其上下文的生命周期内才有效,离开了请求的生命周期,其上下文环境不存在了,也就无法赢得request对象了。而位置所说的多样请求hook函数,会挂载在生命周期的例外阶段,因而在其内部都足以访问request对象。

能够动用Flask的内部方法request_context()来塑造2个伸手上下文

from werkzeug.test import EnvironBuilder
ctx = app.request_context(EnvironBuilder('/','http://localhost/').get_environ())
ctx.push()
try:
    print request.url
finally:
    ctx.pop()

对于Flask
Web应用来说,各样请求便是二个独自的线程。请求之间的新闻要完全隔开,制止争论,那就供给接纳到Thread
Local

Thread Local
对象是保存情形的地点,在Python中,1个指标的意况都被保存在对象指导的一个字典中,**Thread
Local **则是一种十分的对象,它的“状态”对线程隔开分离 ——
也等于说各类线程对二个 Thread Local
对象的修改都不会潜移默化其它线程。那种对象的落到实处原理也十分简单,只要以线程的
ID 来保存多份状态字典即可,如同遵照门牌号隔离的一格一格的邮箱。
在Python中取得Thread Local最简便的法门是threading.local()

>>> import threading
>>> storage = threading.local()
>>> storage.foo = 1
>>> print(storage.foo)
1
>>> class AnotherThread(threading.Thread):
...         def run(self):
...             storage.foo = 2
...             print(storage.foo) # 这这个线程里已经修改了
>>>
>>> another = AnotherThread()
>>> another.start()
2
>>> print(storage.foo) # 但是在主线程里并没有修改
1

之所以只要有Thread Local对象,就能让同贰个目的在八个线程下做随地境隔断。

Flask是二个基于WerkZeug达成的框架,因而Flask的App Context和Request
Context是依据WerkZeug的Local
Stack的落到实处。那二种上下文对象类定义在flask.ctx中,ctx.push会将近日的上下文对象压栈压入flask._request_ctx_stack中,这个_request_ctx_stack同样也是个Thread
Local对象,也正是在各样线程中都不雷同,上下文压入栈后,再一次呼吁的时候都以透过_request_ctx_stack.top在栈的上边取,所取到的不可磨灭是属于本身线程的指标,这样不一样线程之间的上下文就完了了隔开分离。请求甘休后,线程退出,ThreadLocal本地变量也随即销毁,然后调用ctx.pop()弹出上下文对象并回收内存。


恳请钩子

有时要求在伸手从前或以往执行代码会很有用。例如,
在乞求开首时大家只怕须要创制数据库连接/认证发起呼吁的用户。为了制止在每种视图函数中都动用重复的代码,
Flask 提供了注册通用函数的机能,
注册的函数可在伸手被分发到视图函数从前/之后被调用。

伸手钩子 使用装饰器实现。 Flask 援救以下 4 种钩子:

  • before_first_request: 注册四个函数, 在拍卖第一个恳请从前运维。
  • before_request: 注册3个函数, 在每一遍请求在此之前运转。
  • after_request: 注册三个函数, 倘若未有未处理的百般抛出,
    则在每一遍请求之后运营。
  • teardown_request: 注册1个函数, 即便有未处理的要命抛出,
    也在历次请求之后运营。

在呼吁钩子和视图函数之间共享数据貌似接纳上下文全局变量 g。 例如
before_request 处理程序能够从数据库中加载已登录用户, 并将其保存到
g.user 中。随后调用视图函数时, 视图函数再使用 g.user 获取用户。

@app.route(“/”) #
take note of this decorator syntax, it’s a common
pattern

利用上下文

从一个 Flask App 读入配置并运维上马,就进来了 App
Context,在个中大家得以访问布署文件、打开财富文件、通过路由规则反向结构
ULX570L。可以看上面1段代码:

from flask import Flask, current_app
app = Flask('__name__')

@app.route('/')
def index():
    return 'Hello, %s!' % current_app.name

current_app是一个本地代理,它的花色是werkzeug.local.
LocalProxy
,它所代理的就是大家的app对象,也正是说current_app ==
LocalProxy(app)
。使用current_app是因为它也是1个ThreadLocal变量,对它的变动不会影响到其余线程。能够通过current_app._get_current_object()主意来得到app对象。current_app只可以在伸手线程里存在,由此它的生命周期也是在利用上下文里,离开了使用上下文也就不可能选择。

app = Flask('__name__')
print current_app.name

同等会报错:

RuntimeError: working outside of application context

和伸手上下文一样,同样能够手动创立应用上下文:

with app.app_context():
    print current_app.name

这里的with语句和** with open() as
f同一,是Python提供的语法糖,能够为提供上下文环境省略简化一部分办事。那里就简化了其压栈和出栈操作,请求线程创立时,Flask会创造应用上下文对象,并将其压入flask._app_ctx_stack**的栈中,然后在线程退出前将其从栈里弹出。
运用上下文也提供了装饰器来修饰hook函数,@teardown_request,它会在上下文生命周期结束前,也正是_app_ctc_stack出栈前被调用,能够用上面包车型客车代码调用验证:

@app.teardown_appcontext
def teardown_db(exception):
    print 'teardown application'

亟待留意的牢笼
当 app = Flask(name)构造出三个 Flask App 时,App Context
并不会被自动推入 Stack 中。所以那时候 Local Stack
的栈顶是空的,current_app也是 unbound 状态。

>>> from flask import Flask
>>> from flask.globals import _app_ctx_stack, _request_ctx_stack
>>>
>>> app = Flask(__name__)
>>> _app_ctx_stack.top
>>> _request_ctx_stack.top
>>> _app_ctx_stack()
<LocalProxy unbound>
>>>
>>> from flask import current_app
>>> current_app
<LocalProxy unbound>

在编辑离线脚本的时候,假诺直白在二个 Flask-SQLAlchemy 写成的 Model
上调用 User.query.get(user_id),就会碰着 RuntimeError。因为那时 App
Context 还没被推入栈中,而 Flask-SQLAlchemy 须求数据库连接新闻时就会去取
current_app.config,current_app 指向的却是
_app_ctx_stack为空的栈顶。
消除的诀借使运作脚本正文此前,先将 App 的 App Context
推入栈中,栈顶不为空后 current_app那一个 Local Proxy 对象就自然能将“取
config 属性” 的动作转载到当前 App 上。

>>> ctx = app.app_context()
>>> ctx.push()
>>> _app_ctx_stack.top
<flask.ctx.AppContext object at 0x102eac7d0>
>>> _app_ctx_stack.top is ctxTrue
>>> current_app<Flask '__main__'>
>>>
>>> ctx.pop()
>>> _app_ctx_stack.top
>>> current_app
<LocalProxy unbound>

那么为啥在应用运维时不须要手动 app_context().push()呢?因为 Flask App
在作为 WSGI Application 运维时,会在各种请求进入的时候将请求上下文推入
_request_ctx_stack中,而请求上下文一定是 App
上下文之中,所以推入部分的逻辑有如此一条:假设发现
_app_ctx_stack为空,则隐式地推入1个 App 上下文。


响应

Flask 调用视图函数后, 会将其重回值作为响应的剧情。超越二分之一情景下,
响应正是三个粗略的字符串, 作为 HTML 页面回送客户端。

在响应的公文之后添加三个状态码:

@app.route('/')
def index():
    return '<h1>Bad Request</h1>', 400

代表请求无效。

视图函数重临的响应还足以收到第一个参数,
那是3个由首部(header)组成的字典, 能够增加到 HTTP 响应中。

Flask 还足以回来 Response 对象。 make_response() 函数可接受 六分之三/三个参数(和视图函数的重返值一样), 并重回一个 Response 对象。

from flask import make_response
@app.route('/')
def index():
    response = make_response('<h1>This document carries a cookie!</h1>')
    response.set_cookie('answer', '42')
    return response

重定向是一种十分的响应类型。那种响应类型未有页面文书档案,
只告诉浏览器二个新的地方用于加载新页面。Flask 已经提供了 redirect()
函数:

from flask import redirect
@app.route('/')
def index():
    return redirect('http://www.example.com')

再有1种奇特的 abort 响应, 用于处理错误:

from flask import abort
@app.route('/user/<id>')
def get_user(id):
    user = load_user(id):
    if not user:
        abort(404)
    return '<h1>Hello, %s!</h1>' % user.name

def hello():

商讨一些

  • 既然在 Web 应用运转时里,应用上下文 和 请求上下文 都以 Thread Local
    的,那么为何还要独立贰者?
  • 既然如此在Web应用运行时中,1个线程同时只处理2个请求,那么
    _req_ctx_stack和
    _app_ctx_stack肯定都以只有三个栈顶成分的。那么为啥还要用“栈”那种协会?
  • App和Request是怎么关联起来的?

翻看资料后意识第三个难点是因为设计初衷是为了能让多个以上的Flask应用共存在三个WSGI应用中,那样在伸手中,供给经过采用上下文来博取当前恳求的使用音讯。
4858.com,而第一个难题则是须要怀想在非Web
Runtime的条件中选择的时候,在几个App的时候,无论有多少个App,只要主动去Push它的app
context,context stack就会积累起来,这样,栈顶永远是当前操作的 App
Context。当四个 App Context
甘休的时候,相应的栈顶成分也随即出栈。若是在举办进度中抛出了老大,对应的
App Context 中注册的 teardown函数被流传带有特别新闻的参数。
这么一来就表达了那多个难题,在这种单线程运转条件中,唯有栈结构才能保存七个Context 并在其中固定出哪位才是“当前”。而离线脚本只须要 App
关联的上下文,不要求结构出请求,所以 App Context 也相应和 Request
Context 分离。
其七个难点

能够参见一下源码看一下Flask是怎么落到实处的伸手上下文:

# 代码摘选自flask 0.5 中的ctx.py文件,
class _RequestContext(object):
    def __init__(self, app, environ):
        self.app = app 
        self.request = app.request_class(environ) 
        self.session = app.open_session(self.request) 
        self.g = _RequestGlobals()

Flask中的使用_RequestContext的方式如下:

class Flask(object): 
    def request_context(self, environ): 
        return _RequestContext(self, environ)

在Flask类中,每趟请求都会调用那一个request_context函数。那些函数则会创立1个_RequestContext对象,该指标急需接受WerkZeug中的environ对象作为参数。这一个指标在创设时,会把Flask实例自身作为实参传进去,所以就算每一遍http请求都创立三个_RequestContext对象,然则每一遍创设的时候传出的都以同二个Flask对象,由此:

由同三个Flask对象相应请求成立的_RequestContext对象的app成员变量都共享二个application

经过Flask对象中成立_RequestContext对象,并将Flask自己作为参数字传送入的办法贯彻了三个request
context对应3个application context。
下一场能够看self.request = app.request_class(environ)这句
鉴于app成员变量是app = Flask(name)
这一个指标,所以app.request_class就是Flask.request_class,而在Flask类的定义中:

request_class = Request
    class Request(RequestBase):
        ....

所以self.request =
app.request_class(environ)实际上是创设了一个Request对象。由于一个http请求对应叁个_RequestContext对象的始建,而种种_RequestContext对象的创建对应3个Request对象的开创,所以,每一种http请求对应三个Request对象。

因此
application 就是指app = Flask(name)对象
request 正是对应每回http 请求创立的Request对象
Flask通过_RequestContext将App与Request关联起来

仅为祥和学习用,汇总了查看的材质,记录了有的笔记,转发请表明资料中原作者。

参考资料
Flask 的 Context
机制
Flask进阶种类之上下文
Flask上下文的贯彻

Flask 扩展

    return “Hello
World!”

使用Flask-Script援救命令行选项

Flask 的开发 Web 服务器匡助广大起动设置选项,但只幸而剧本中作为参数字传送给
app.run()函数。那种办法并不要命利于,传递设置选项的精彩形式是接纳命令行参数。

Flask-Script 是四个 Flask 扩张,为 Flask
程序添加了1个指令行解析器。Flask-Script
自带了壹组常用选项,而且还协理自定义命令。

# 安装
(venv) $ pip install flask-script

要选用 flask-script 须求在 hello.py 修改下程序:

from flask import Flask
from flask.ext.script import Manager

app = Flask(__name__)
manager = Manager(app)

@app.route('/')
def index():
    return '<h1>Hello,World</h1>'

if __name__ == '__main__':
    manager.run()

专为 Flask 开发的扩展都暴漏在 flask.ext 命名空间下。Flask-Script
输出了三个名称叫Manager 的类,可从 flask.ext.script 中引进。

本条增添的开首化方法也适用于其它很多扩大:把 app
实例作为参数字传送给扩充的构造函数,开头化主类的实例。创造的靶子可以在挨家挨户扩充中动用。在此处,服务器由
manager.run() 运营,运行后就能解析命令行了。

留神, 在 Python 3 中要这么导入 flask-script 扩充, from
flask_script import Manager

现今运营 hello.py,会显示四个帮忙消息:

$ python hello.py
usage: hello.py [-h] {shell,runserver} ...

positional arguments:
  {shell,runserver}
      shell           在 Flask 应用上下文中运行 Python shell
      runserver  运行 Flask 开发服务器:app.run()

optional arguments:
  -h, --help       显示帮助信息并退出

shell 命令用于在先后的上下文中运营 Python shell
会话。你能够动用这几个会话中运维保障职分或测试,还可调节和测试分外。顾名思义,
runserver 命令用来运行 Web 服务器。运营 python hello.py runserver
将以调节和测试情势运营 Web 服务器,但是我们还有好多精选可用:

$ python hello.py runserver --help
usage: hello.py runserver [-?] [-h HOST] [-p PORT] [--threaded]
                          [--processes PROCESSES] [--passthrough-errors] [-d]
                          [-D] [-r] [-R]

--host 参数是个很有用的选项,它报告 Web
服务器在哪个网络接口上监听来自客户端的连日。暗中同意意况下,Flask 开发 Web
服务器监听 localhost
上的连年,所以只接受来自服务器所在总结机发起的接连。下述命令让 Web
服务器监听公共互连网接口上的连接,允许同网中的别的计算机连接服务器:

(venv) $ python hello.py runserver --host 0.0.0.0
* Running on http://0.0.0.0:5000/
* Restarting with reloader

未来,Web 服务器可接纳 http://a.b.c.d:5000/
互连网中的任一台计算机举办走访,在那之中 “a.b.c.d” 是服务器所在计算机的外网 IP
地址。

 

if __name__ == “__main__”:

    app.run()

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有