学习笔记,的主干协会

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…

上下文这些概念多见于小说中,是一句话中的语境,也便是言语情形。一句莫明其妙的话出现会让人不明白什么意思,假使有语言情形的辨证,则会更好,那正是语境对语意的影响。
上下文是一种特性的不改变种类,为驻留在情状内的目的定义情状。在目标的激活进度中开创上下文,对象被陈设为须求有些活动服务,如壹道、事务、实时激活、安全性等等。

初始化

全部 Flask 程序都不可能不创制四个 app 实例。Web 服务器使用 Web
服务器网关接口协议(Web Server Gateway Interface,
WSGI)把吸收自客户端的兼具请求都传送给那一个对象拍卖。 app 实例是 Flask
类的对象:

from flask import Flask
app = Flask(__name__)

Flask 类的构造函数自有一个不可能不钦命的参数, 即 app 主模块或包的名字。

Flask 用 name 这些参数决定程序的根目录,
以便稍后能够找到相对于程序根目录的资源文本地点。

安装 Flask

比方在管理器中,相对于经过来讲,上下文正是进程试行时的条件。具体来说正是各种变量和多少,包涵富有的寄存器变量、进程展开的文本、内存音讯等。能够明白上下文是条件的二个快速照相,是三个用于保存情形的目标。在先后中大家所写的函数大都不是独立完整的,在利用一个函数实现自个儿效益的时候,很恐怕要求同其它的片段进行交互,需求任何外部情形变量的支撑,上下文就是给外部意况的变量赋值,使函数能正确运营。

路由和视图函数

客户端(比如 Web 浏览器)把请求发送给 Web 服务器, Web
服务器再把请求发送给 Flask app 实例。 app 实例必要了然对各类 U奥迪Q7L
请求运营哪些代码, 所以 app 实例保存了1个 U昂科拉L 到 Python
函数的照射关系。管理 U路虎极光L 和函数之间关系的次第名称叫路由。

在 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
类型也是字符串, 但不把斜线作为分割符, 而将其当做动态片段的1局地。

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

pip install Flask

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

开行服务器

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

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

__name__ == '__main__' 确定保证了唯有直接 试行这么些剧本时才开动 Web
服务器。纵然那几个本子由其他脚本引入, 程序假定父级脚本会运营区别的服务器,
由此不会举行 app.run()

服务器运营后会进入轮询, 等待并管理请求,
轮询会一向运行,直到程序截止,比如按 Ctrl-C 键。

 

浅显地解释一下application contextrequest context

三个整机的 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 使用上下文让特定的变量在每一个线程中全局可访问,
与此同时却不会干扰别的线程。

二拾三十二线程 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
的 UCRUISERL 映射中查找请求的 U科雷傲L 来产生那个任务。 U福睿斯L 映射是 U本田UR-VL
和视图函数之间的应和关系。 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 增添的特殊路由, 用于访问静态文件。

U奥迪Q7L 映射中的 HEAD、OPTIONS、GET 是呼吁方法。Flask
为种种路由都内定了请求方法, 那样不一样的伸手发送到同样的 UEscortL 上时,
会使用不相同的视图函数举办拍卖。 HEAD 和 OPTIONS 方法由 Flask 自动管理,
因而得以说地点的 app 中 U安德拉L 映射中的 三 个路由都施用 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对象却并不是大局的,因为当我们不管声雅培(Abbott)个函数的时候,举个例子:

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()来构建二个伸手上下文

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 **则是一种特有的对象,它的“状态”对线程隔开分离 ——
也正是说各种线程对3个 Thread Local
对象的修改都不会潜移默化其它线程。那种对象的贯彻原理也万分简单,只要以线程的
ID 来保存多份状态字典就能够,就好像根据门牌号隔离的一格1格的邮箱。
在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是1个基于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 扶助以下 四 种钩子:

  • before_first_request: 注册叁个函数, 在拍卖第一个恳请此前运维。
  • before_request: 注册贰个函数, 在每趟请求以前运转。
  • after_request: 注册叁个函数, 如若未有未管理的相当抛出,
    则在每便请求之后运营。
  • teardown_request: 注册3个函数, 即便有未管理的分外抛出,
    也在历次请求之后运转。

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

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

利用上下文

从1个 Flask App 读入配置并运转上马,就进来了 App
Context,在其间大家得以访问安插文件、展开能源文件、通过路由规则反向组织U昂CoraL。能够看上边一段代码:

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

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

current_app是1个地点代理,它的门类是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>

在编写制定离线脚本的时候,倘若直接在1个 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为空,则隐式地推入贰个 App 上下文。


响应

Flask 调用视图函数后, 会将其再次来到值作为响应的内容。大很多状态下,
响应就是3个轻巧易行的字符串, 作为 HTML 页面回送客户端。

在响应的公文之后增加一个状态码:

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

代表请求无效。

视图函数再次来到的响应还是能够吸收第二个参数,
那是一个由首部(header)组成的字典, 能够拉长到 HTTP 响应中。

Flask 还足以回来 Response 对象。 make_response() 函数可接受 1/2/三个参数(和视图函数的重回值一样), 并再次来到1个 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

美高梅开户网址,重定向是壹种奇特的响应类型。那种响应类型没有页面文书档案,
只告诉浏览器2个新的地址用于加载新页面。Flask 已经提供了 redirect()
函数:

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

还有一种尤其的 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个呼吁,那么
    _req_ctx_stack和
    _app_ctx_stack肯定都是唯有多少个栈顶成分的。那么为啥还要用“栈”那种结构?
  • App和Request是怎么关联起来的?

查看资料后发觉第1个难题是因为布置初衷是为着能让三个以上的Flask应用共设有叁个WSGI应用中,那样在央浼中,须求通过行使上下文来博取当前恳请的行使音讯。
而第一个难点则是索要思索在非Web
Runtime的条件中央银行使的时候,在八个App的时候,无论有多少个App,只要主动去Push它的app
context,context stack就集聚成堆起来,那样,栈顶长久是当前操作的 App
Context。当1个 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函数。这几个函数则会创建2个_RequestContext对象,该对象须求接受WerkZeug中的environ对象作为参数。这几个目标在开即刻,会把Flask实例自身作为实参传进去,所以就算每一趟http请求都创立贰个_RequestContext对象,可是每便成立的时候传出的都是同二个Flask对象,由此:

由同1个Flask对象相应请求创造的_RequestContext对象的app成员变量都共享2个application

通过Flask对象中成立_RequestContext目的,并将Flask自个儿作为参数字传送入的方法完成了两个request
context对应叁个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)实际上是创办了1个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
程序增添了二个下令行解析器。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 三 中要如此导入 flask-script 扩张, from
flask_script import Manager

现行反革命运维 hello.py,会呈现3个增派新闻:

$ 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
上的延续,所以只接受来自服务器所在Computer发起的连天。下述命令让 Web
服务器监听公共网络接口上的连日,允许同网中的别的Computer连接服务器:

(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/
互连网中的任1台Computer举办访问,个中 “a.b.c.d” 是服务器所在Computer的外网 IP
地址。

 

if __name__ == “__main__”:

    app.run()

发表评论

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

网站地图xml地图