目录

  • 1. Flask简介
  • 2. wsgiref的简单应用
  • 3. Flask安装
  • 4. werkzeug简介
  • 5. flask快速使用

1. Flask简介

Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。

“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。

默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用

2. wsgiref的简单应用

最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。

如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。

正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口协议来实现这样的服务器软件,让我们专心用Python编写Web业务。这个接口就是WSGI:Web Server Gateway Interface。而wsgiref模块就是python基于wsgi协议开发的服务模块

from wsgiref.simple_server import make_server


def mya(environ, start_response):
    print(environ)
    start_response('200 OK', [('Content-Type', 'text/html')])
    if environ.get('PATH_INFO') == '/index':
        with open('index.html', 'rb') as f:
            data = f.read()

    elif environ.get('PATH_INFO') == '/login':
        with open('login.html', 'rb') as f:
            data = f.read()

    else:
        data = b'<h1>Hello Web</h1>'
    return [data]


if __name__ == '__main__':
    myserver = make_server('127.0.0.1', 4000, mya)
    print('监听4000')
    myserver.serve_forever()
from wsgiref.simple_server import make_server


def mya(environ, start_response):
    print(environ)
    start_response('200 OK', [('Content-Type', 'text/html')])
    if environ.get('PATH_INFO') == '/index':
        with open('index.html', 'rb') as f:
            data = f.read()

    elif environ.get('PATH_INFO') == '/login':
        with open('login.html', 'rb') as f:
            data = f.read()

    else:
        data = b'<h1>Hello Web</h1>'
    return [data]


if __name__ == '__main__':
    myserver = make_server('127.0.0.1', 4000, mya)
    print('监听4000')
    myserver.serve_forever()

3. Flask安装

pip install flask
pip install flask

4. werkzeug简介

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)  # 调用run_simple起服务,参数为ip、端口、要执行的对象
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)  # 调用run_simple起服务,参数为ip、端口、要执行的对象

5. flask快速使用

from flask import Flask
# 实例化产生一个Flask对象
app = Flask(__name__)
# 将‘/’和视图函数index的对应关系添加到路由中
@app.route('/')
def index():
    return 'ok'

if __name__ == '__main__':
    app.run()  # 调用run()方法
from flask import Flask
# 实例化产生一个Flask对象
app = Flask(__name__)
# 将‘/’和视图函数index的对应关系添加到路由中
@app.route('/')
def index():
    return 'ok'

if __name__ == '__main__':
    app.run()  # 调用run()方法

为什么app.run()方法能起服务呢???其实本质上是基于werkzeug调用了run_simple()

app.run()源码

def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
    if os.environ.get("FLASK_RUN_FROM_CLI") == "true":
        from .debughelpers import explain_ignored_app_run
        explain_ignored_app_run()
        return
    if get_load_dotenv(load_dotenv):
        cli.load_dotenv()
        if "FLASK_ENV" in os.environ:
            self.env = get_env()
            self.debug = get_debug_flag()
        elif "FLASK_DEBUG" in os.environ:
            self.debug = get_debug_flag()
    if debug is not None:
        self.debug = bool(debug)
    _host = "127.0.0.1"
    _port = 5000
    server_name = self.config.get("SERVER_NAME")
    sn_host, sn_port = None, None
    if server_name:
        sn_host, _, sn_port = server_name.partition(":")
    host = host or sn_host or _host
    port = int(next((p for p in (port, sn_port) if p is not None), _port))
    options.setdefault("use_reloader", self.debug)
    options.setdefault("use_debugger", self.debug)
    options.setdefault("threaded", True)
    cli.show_server_banner(self.env, self.debug, self.name, False)
    
    from werkzeug.serving import run_simple
    try:
        # 在这里导入并调用了 run_simple 来起服务
        run_simple(host, port, self, **options)  # host、端口
    finally:
        self._got_first_request = False
def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
    if os.environ.get("FLASK_RUN_FROM_CLI") == "true":
        from .debughelpers import explain_ignored_app_run
        explain_ignored_app_run()
        return
    if get_load_dotenv(load_dotenv):
        cli.load_dotenv()
        if "FLASK_ENV" in os.environ:
            self.env = get_env()
            self.debug = get_debug_flag()
        elif "FLASK_DEBUG" in os.environ:
            self.debug = get_debug_flag()
    if debug is not None:
        self.debug = bool(debug)
    _host = "127.0.0.1"
    _port = 5000
    server_name = self.config.get("SERVER_NAME")
    sn_host, sn_port = None, None
    if server_name:
        sn_host, _, sn_port = server_name.partition(":")
    host = host or sn_host or _host
    port = int(next((p for p in (port, sn_port) if p is not None), _port))
    options.setdefault("use_reloader", self.debug)
    options.setdefault("use_debugger", self.debug)
    options.setdefault("threaded", True)
    cli.show_server_banner(self.env, self.debug, self.name, False)
    
    from werkzeug.serving import run_simple
    try:
        # 在这里导入并调用了 run_simple 来起服务
        run_simple(host, port, self, **options)  # host、端口
    finally:
        self._got_first_request = False