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 程序都必须创建1个 app 实例。Web 服务器使用 Web
服务器网关接口协议(Web Server Gateway Interface,
WSGI)把接受自客户端的全部请求都传送给那个对象管理。 app 实例是 Flask
类的靶子:

from flask import Flask
app = Flask(__name__)

Flask 类的构造函数自有八个必须钦命的参数, 即 app 主模块或包的名字。

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

安装 Flask

诸如在Computer中,相对于经过来说,上下文正是进度实践时的条件。具体来讲正是各种变量和数量,包罗具有的寄存器变量、过程展开的文书、内存音信等。能够明白上下文是境况的1个快速照相,是多个用以保存景况的对象。在先后中我们所写的函数大都不是独自完整的,在应用2个函数落成自己功效的时候,比较大概要求同其余的有的举行交互,须要其余外部蒙受变量的支撑,上下文便是给外部意况的变量赋值,使函数能正确运维。

路由和视图函数

客户端(举个例子 Web 浏览器)把请求发送给 Web 服务器, Web
服务器再把请求发送给 Flask app 实例。 app 实例须求驾驭对种种 U逍客L
请求运营哪些代码, 所以 app 实例保存了多个 U奥迪Q5L 到 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
类型也是字符串, 但不把斜线作为分割符, 而将其看做动态片段的一片段。

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

pip install Flask

Flask提供了三种上下文,1种是采取上下文(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

八个总体的 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 服务器会创建2个线程池,
再从线程池中挑选3个线程用于拍卖接收到的央浼。

在 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兰德QashqaiL 来成功这么些任务。 U福特ExplorerL 映射是 UPRADOL
和视图函数之间的照料关系。 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中华VL 映射中的 HEAD、OPTIONS、GET 是呼吁方法。Flask
为每一种路由都钦赐了请求方法, 那样不一样的伸手发送到一样的 U奇骏L 上时,
会使用不一样的视图函数举行管理。 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对象却并不是大局的,因为当大家不管声明一(Wissu)个函数的时候,比如:

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 **则是一种特别的靶子,它的“状态”对线程隔开 ——
也便是说各类线程对1个 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 支持以下 肆 种钩子:

  • before_first_request: 注册2个函数, 在拍卖第一个请求从前运转。
  • before_request: 注册一个函数, 在历次请求以前运营。
  • after_request: 注册三个函数, 假诺未有未管理的百般抛出,
    则在历次请求之后运转。
  • teardown_request: 注册三个函数, 固然有未管理的要命抛出,
    也在历次请求之后运转。

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

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

运用上下文

从四个 Flask App 读入配置并运维上马,就进去了 App
Context,在中间大家得以访问铺排文件、展开资源文件、通过路由规则反向组织U纳瓦拉L。可以看下边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是因为它也是一个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提供的语法糖,可感到提供上下文景况省略简化1部分做事。那里就简化了其压栈和出栈操作,请求线程成立时,Flask会创造应用上下文对象,并将其压入flask._app_ctx_stack**的栈中,然后在线程退出前将其从栈里弹出。
动用上下文也提供了装饰器来修饰hook函数,@teardown_request,它会在上下文生命周期甘休前,也正是_app_ctc_stack出栈前被调用,能够用上边包车型客车代码调用验证:

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

内需小心的骗局
当 app = Flask(name)构造出2个 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为空,则隐式地推入三个 App 上下文。


响应

Flask 调用视图函数后, 会将其重回值作为响应的内容。大诸多情景下,
响应正是一个简短的字符串, 作为 HTML 页面回送客户端。

在响应的文书之后增加三个状态码:

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

代表请求无效。

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

Flask 还足以重回 Response 对象。 make_response() 函数可接受 一半/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

重定向是一种独特的响应类型。那种响应类型未有页面文书档案,
只告诉浏览器3个新的地方用于加载新页面。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
    的,那么为何还要独立2者?
  • 既是在Web应用运维时中,多少个线程同时只管理二个伸手,那么
    _req_ctx_stack和
    _app_ctx_stack明确都以唯有多少个栈顶成分的。那么为何还要用“栈”这种结构?
  • App和Request是怎么关联起来的?

查阅资料后开采第三个难题是因为设计初衷是为着能让七个以上的Flask应用共设有3个WSGI应用中,那样在央求中,必要通过运用上下文来获得当前呼吁的运用音信。
而第四个难点则是内需思索在非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函数。那些函数则会创造一个_RequestContext对象,该对象须求抽出WerkZeug中的environ对象作为参数。这么些目的在开创时,会把Flask实例自身作为实参传进去,所以固然每一次http请求都创建2个_RequestContext对象,但是每一次创制的时候传出的都以同三个Flask对象,因此:

由同二个Flask对象相应请求成立的_RequestContext对象的app成员变量都共享一个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)实际上是成立了一个Request对象。由于贰个http请求对应三个_RequestContext对象的创制,而各类_RequestContext对象的创始对应多个Request对象的创制,所以,每种http请求对应一个Request对象。

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

仅为自己读书用,汇总了翻看的材质,记录了有个别笔记,转发请申明资料中原作者。

参考资料
Flask 的 Context
机制
Flask进阶体系之上下文
Flask上下文的完结

Flask 扩展

    return “Hello
World金沙注册送58,!”

动用Flask-Script接济命令行选项

Flask 的付出 Web 服务器匡助广大起动设置选项,但不得不在剧本中作为参数传给
app.run()函数。那种办法并不10分便利,传递设置选项的不错方式是采纳命令行参数。

Flask-Script 是2个 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
输出了3个名称为Manager 的类,可从 flask.ext.script 中引进。

那些扩张的起首化方法也适用于其余众多增加:把 app
实例作为参数字传送给扩充的构造函数,伊始化主类的实例。成立的靶子足以在1壹扩大中选用。在此处,服务器由
manager.run() 运维,运转后就能解析命令行了。

留意, 在 Python 三 中要那样导入 flask-script 扩大, from
flask_script import Manager

前几日运转 hello.py,会显得2个救助音信:

$ 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台微型计算机实行走访,在那之中 “a.b.c.d” 是服务器所在Computer的外网 IP
地址。

 

if __name__ == “__main__”:

    app.run()

相关文章

网站地图xml地图