威尼斯人线上娱乐

上学笔记,的主导构造

23 4月 , 2019  

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

譬如在Computer中,相对于经过来说,上下文就是进度实行时的条件。具体来讲正是逐1变量和数据,包蕴全体的寄存器变量、进度打开的文书、内部存款和储蓄器新闻等。能够精晓上下文是情形的多个快速照相,是二个用于保存景况的目的。在程序中我们所写的函数大都不是单独完整的,在应用二个函数完结本人职能的时候,很恐怕须要同其余的局地开始展览交互,供给任何外部情形变量的支持,上下文正是给外部情形的变量赋值,使函数能科学运转。

路由和视图函数

客户端(比如 Web 浏览器)把请求发送给 Web 服务器, Web
服务器再把请求发送给 Flask app 实例。 app 实例须要领悟对各类 URL
请求运转哪些代码, 所以 app 实例保存了2个 U途乐L 到 Python
函数的照耀关系。管理 UXC60L 和函数之间关系的主次名称为路由。

在 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

贰个一体化的 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个参数。如若视图函数还要访问另外对象,
那么视图函数会变得愈加臃肿和不便保险。

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

10二线程 Web 服务器会创设三个线程池,
再从线程池中选取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
的 URubiconL 映射中查找请求的 U牧马人L 来产生那个职责。 UPRADOL 映射是 U昂科拉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 增添的异样路由, 用于访问静态文件。

UCRUISERL 映射中的 HEAD、OPTIONS、GET 是伸手方法。Flask
为每一种路由都钦点了请求方法, 这样区别的伸手发送到同样的 U大切诺基L 上时,
会使用不一样的视图函数进行拍卖。 HEAD 和 OPTIONS 方法由 Flask 自动管理,
因而得以说上边的 app 中 UPRADOL 映射中的 三 个路由都采用 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对象却并不是全局的,因为当我们随意声喜宝(Hipp)个函数的时候,举例:

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 **则是一种特别的目的,它的“状态”对线程隔断 ——
相当于说每一种线程对一个 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对象,就能让同2个目标在多少个线程下产生情状隔断。

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: 注册一个函数, 在历次请求以前运营。
  • 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

使用上下文

从3个 Flask App 读入配置并运转上马,就进来了 App
Context,在里面大家得以访问陈设文件、张开能源文件、通过路由规则反向结构
U锐界L。能够看上边壹段代码:

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

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

current_app是2个本土代理,它的门类是werkzeug.local.
LocalProxy
,它所代理的便是大家的app对象,也等于说current_app ==
LocalProxy(app)
。使用current_app是因为它也是2个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)构造出三个 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 调用视图函数后, 会将其再次回到值作为响应的内容。大好些个情景下,
响应正是2个总结的字符串, 作为 HTML 页面回送客户端。

在响应的文件之后加多一个状态码:

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

代表请求无效。

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

Flask 还是能够回去 Response 对象。 make_response() 函数可承受 百分之五十/2个参数(和视图函数的重临值同样), 并再次来到一个 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')

再有一种特有的 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应用运转时中,3个线程同时只管理三个呼吁,那么
    _req_ctx_stack和
    _app_ctx_stack肯定都是只有贰个栈顶元素的。那么为啥还要用“栈”那种布局?
  • 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对象,可是每一趟创建的时候传出的都是同贰个Flask对象,因而:

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

经过Flask对象中创立_RequestContext目的,并将Flask自个儿作为参数字传送入的点子贯彻了八个request
context对应1个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)实际上是创制了3个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()函数。那种办法并不十二分利于,传递设置选项的大好情势是选用命令行参数。

Flask-Script 是3个 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
服务器监听公共网络接口上的连年,允许同网中的其余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/
网络中的任壹台微型Computer实行走访,在那之中 “a.b.c.d” 是服务器所在计算机的外网 IP
地址。

 

if __name__ == “__main__”:

    app.run()


相关文章

发表评论

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

网站地图xml地图