【亚洲必赢官网】的着力构造,学习笔记

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

譬如说在管理器中,相对于经过来讲,上下文正是经过施行时的情况。具体而言便是各类变量和数目,包蕴具备的寄存器变量、进程张开的文书、内部存款和储蓄器消息等。能够知道上下文是条件的一个快速照相,是3个用以保存情形的对象。在程序中大家所写的函数大都不是单身完整的,在动用三个函数完毕自己效益的时候,很恐怕必要同其余的部分进行交互,需求此外外部境况变量的支撑,上下文正是给外部情形的变量赋值,使函数能准确运转。

路由和视图函数

客户端(举例 Web 浏览器)把请求发送给 Web 服务器, Web
服务器再把请求发送给 Flask app 实例。 app 实例需求掌握对每一个 U卡宴L
请求运维哪些代码, 所以 app 实例保存了多个 U福特ExplorerL 到 Python
函数的映照关系。管理 U奥迪Q三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提供了二种上下文,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 请求。

要让视图函数能访问伸手对象
3个同理可得的办法是把请求对象作为参数字传送递给视图函数,
不过那会招致程序中每种视图函数都扩大1个参数。尽管视图函数还要访问别的对象,
那么视图函数会变得愈加臃肿和难以保证。

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

10贰线程 Web 服务器会创建三个线程池,
再从线程池中甄选2个线程用于拍卖接收到的呼吁。

在 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
的 UHavalL 映射中查找请求的 U路虎极光L 来完结这么些职分。 U普拉多L 映射是 UBMWX五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 增加的特殊路由, 用于访问静态文件。

U兰德帕杰罗L 映射中的 HEAD、OPTIONS、GET 是伸手方法。Flask
为每一个路由都内定了请求方法, 那样差别的乞求发送到一样的 U汉兰达L 上时,
会使用不一致的视图函数实行拍卖。 HEAD 和 OPTIONS 方法由 Flask 自动管理,
因而得以说地方的 app 中 UEnclaveL 映射中的 三 个路由都利用 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对象却并不是大局的,因为当大家不管声飞鹤个函数的时候,举例:

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中,多少个目标的情事都被保存在对象带领的几个字典中,**Thread
Local **则是壹种万分的对象,它的“状态”对线程隔绝 ——
也便是说各样线程对2个 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对象,就能让同3个目的在七个线程下成功情状隔开分离。

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: 注册三个函数, 在处理第一个恳请此前运转。
  • before_request: 注册二个函数, 在历次请求以前运维。
  • 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

利用上下文

从2个 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提供的语法糖,可以为提供上下文境况省略简化一部分干活。那里就简化了其压栈和出栈操作,请求线程创造时,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为空,则隐式地推入三个 App 上下文。


响应

Flask 调用视图函数后, 会将其重回值作为响应的剧情。大多数情景下,
响应就是三个简便的字符串, 作为 HTML 页面回送客户端。

在响应的文书之后增多一个状态码:

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

意味着请求无效。

视图函数再次来到的响应还足以收到第伍个参数,
那是一个由首部(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')

再有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
    的,那么为啥还要独立2者?
  • 既是在Web应用运转时中,1个线程同时只管理2个伸手,那么
    _req_ctx_stack和
    _app_ctx_stack确定都以只有1个栈顶成分的。那么为啥还要用“栈”那种结构?
  • App和Request是怎么关联起来的?

翻看资料后发掘第三个难点是因为安排初衷是为了能让多少个以上的Flask应用共存在三个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函数。这些函数则会创立2个_RequestContext对象,该对象急需抽取WerkZeug中的environ对象作为参数。这么些目的在开立刻,会把Flask实例本人作为实参传进去,所以即使每一次http请求都成立一个_RequestContext对象,不过每便创立的时候传出的都以同2个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!”

使用Flask-Script帮助命令行选项

Flask 的成本 Web 服务器援助广大早先设置选项,但只能在剧本中作为参数字传送给
app.run()函数。那种方式并不10分造福,传递设置选项的地道形式是使用命令行参数。

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
实例作为参数字传送给扩展的构造函数,初步化主类的实例。创设的靶子能够在一1扩充中选择。在此处,服务器由
manager.run() 启动,运营后就能解析命令行了。

只顾, 在 Python 三 中要那样导入 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
上的接连,所以只接受来自服务器所在Computer发起的连接。下述命令让 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/
互连网中的任1台计算机实行走访,在这之中 “a.b.c.d” 是服务器所在计算机的外网 IP
地址。

 

if __name__ == “__main__”:

    app.run()

网站地图xml地图