Flask是一个Python编写的Web 微框架,让我们可以使用Python语言快速实现一个网站或Web服务,
在介绍Flask之前首先来聊下它和Django的联系以及区别
WSGI(web服务器网关接口)是python中用来规定web服务器如何与python Web服务器如何与Python Web程序进行沟通的标准,本质上就是一个socket服务端。而 Werkzeug模块 就是WSGI一个具体的实现
flask性能上基本满足一般web开发的需求, 并且灵活性以及可扩展性上要优于其他web框架, 对各种数据库的契合度都非常高
关键词:
pip安装
pip install Flask
除了Flask包外,同时被安装的还有5个依赖包,它们的主要介绍如表(1-1)所示。
包名及版本 | 功能 |
---|---|
Jinja2-2.10 | 渲染模板引擎工具集 |
MarkupSafe-1.1.0 | 可以识别HTML转义规则。HTML字符转义工具集 |
Werkzeug-0.14.1 | Web 框架的底层库,提供了请求及响应以及开发服务器的功能,简称WSGI工具集 |
click-7.0 | 命令行工具集 |
itsdangerous-1.1.0 | 加密工具集 |
项目目录详解:
“static文件夹”用于存放各种静态文件 css、js、图片等等
“templates文件夹”用于存放html模板文件
“app.py”为我们的主文件 ,启动项目需要启动该文件
注意 app.py 文件的名字我们可以自由命名,但是除了flask.py 这种和Flask库相冲突的名字
from flask import Flask
app = Flask(__name__)
导入我们安装好的flask包,通过flask包导入Flask类,Flask类即为Flask的核心,实例化这个Flask类的到一个实例化对象app。
__name__这个特殊的参数:Python会根据所处的模块来赋予__name__变量相应的值,对于我们的程序来说(app.py),这个值为app。
@app.route('/')
def hello_world():
return 'Hello World!'
如果有过对其他web框架的了解,相信看见这个已经看出了一些门道。没错这个 @app.route(‘/’)就是用来匹配url的,在我们的flask里面是以装饰器来实现的,装饰器引用的也是我们上面实例化核心类出来的对象。
那么如果路由下面跟的函数什么呢 ?没错就是我们的视图函数,如果匹配到了路由就会触发我们的视图函数执行,并且return回具体的数据给前端或者移动端。
不是很理解没关系,我们先大概有个印象,会在接下来的章节详细讲解路由以及视图函数的使用
if __name__ == '__main__':
app.run()
先不管逻辑判断,先看 app.run(), app.run()源码如下去阅读源码不难发现,在内部定义了默认的 ip+端口为127.0.0.1:5000,并且调用了werkzeug.serving为我们创建了一个开发服务器(由依赖包Werkzeug提供),对套接字有一定了解的朋友,其内部就是做了一个循环监听的功能以便交互.
关键词:app.run()实现了flask程序在开发环境下运行起来,并且默认ip和端口是127.0.0.1:5000。
def run(self, host=None, port=None, debug=None,
load_dotenv=True, **options):
...
_host ='127.0.0.1'
_port = 5000
...
host = host or sn_host or _host
port = int(port or sn_port or _port)
...
from werkzeug.serving import run_simple
try:
run_simple(host, port, self, **options)
finally:
# reset the first request information if the development server
# reset normally. This makes it possible to restart the server
# without reloader and that stuff from an interactive shell.
self._got_first_request = False
在第三部分中还有一个if判断,那么这个判断的作用是什么呢,有python基础的朋友对这个写法大概不陌生,if逻辑判断时只有本文件为执行文件的时候才会执行,为什么要这么设计呢?因为在开发环境我们是以app.py作为执行文件,但是在真实的生产环境下 ,此文件会作为被调用的文件,并且真实的生成环境不会用到app.run()做监听分配, 原因是性能太低了,
关键词:保证了app.run()只用于开发环境,并且不影响真实的生产环境。
三部分串讲
导入Flask的核心类实例化对象app,然后app作为装饰器使用匹配url分发给下面的视图函数,然后执行该页面会触发app调用run()方法运行起来整个项目。
Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库。这里稍微说一下, werkzeug 不是一个web服务器,也不是一个web框架,而是一个工具包,官方的介绍说是一个 WSGI 工具包,它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等 。
代码示例:
from werkzeug.wrappers import Request, Response
@Request.application
def hello(request):
return Response('Hello World!')
if __name__ == '__main__':
from werkzeug.serving import run_simple
run_simple('localhost', 4000, hello)
看到了这个wekzeug是不是特别像我们的flask代码,没错我们的flask正是依赖于这个werkzeug模块,由wekzeug模块实现了socket服务端的功能,hello必然是加括号运行了,才会执行hello里面的代码,而在我们的flask中app.run()会调用run_simple(host, port, self, **options)把上面代码例子的hello替换成了self也就是app。app()会触发Flask类的__call__方法。
所以所flask程序的入口就在__call__方法中,而__call__方法返回self.wsgi_app(environ, start_response),所以整个程序的执行过程都在 self.wsgi_app(environ, start_response)中.
#1
app.run() 调用 werkzeug.serving的run_simple(host, port, self, **options)
#2
self()等价于app(), app()调用Flask类的__call__方法
#3
Flask类的__call__方法返回了 self.wsgi_app(environ, start_response)
# 4
flask程序的执行过程都在 self.wsgi_app(environ, start_response)中
具体代码:
def run(self, host=None, port=None, debug=None,
load_dotenv=True, **options):
...
_host ='127.0.0.1'
_port = 5000
...
host = host or sn_host or _host
port = int(port or sn_port or _port)
...
from werkzeug.serving import run_simple
try:
run_simple(host, port, self, **options)
finally:
# reset the first request information if the development server
# reset normally. This makes it possible to restart the server
# without reloader and that stuff from an interactive shell.
self._got_first_request = False
def __call__(self, environ, start_response):
"""The WSGI server calls the Flask application object as the
WSGI application. This calls :meth:`wsgi_app` which can be
wrapped to applying middleware."""
return self.wsgi_app(environ, start_response)
...
def wsgi_app(self, environ, start_response):
ctx = self.request_context(environ)
error = None
try:
try:
ctx.push()
response = self.full_dispatch_request()
except Exception as e:
error = e
response = self.handle_exception(e)
except:
error = sys.exc_info()[1]
raise
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
ctx.auto_pop(error)
关键词:
Werkzeug是一个WSGI工具包,本质上是一个socket服务端。
flask基于Werkzeug,flask只保留了web开发的核心功能。
flask的执行过程都在def wsgi_app(self, environ, start_response):中
运行起来我们的flask项目,也可以在app.py直接右键run启动项目
然后访问http://127.0.0.1:5000/
强调以后我们创建flask项目不要用pycharm自带的flask快捷方式创建,上边的快捷创建方式是便于讲解和理解,真实的生产环境更推荐直接创建一个空的python项目