Flask-0-最小原型

Posted jiangmingbai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask-0-最小原型相关的知识,希望对你有一定的参考价值。

一、从selenium的原理讲起

selenium操作游览器是需要webderiver驱动的,这个驱动其实就可以理解为服务应用(application),selenium只是通过HTTP协议向webdriver发送请求,webdriver接收到请求后,在去驱动游览器做一些列的操作。

我们打开双击运行webdriver.exe,然后通过游览器访问本地localhost:port,是可以访问通的。其实webdriver此时就开启了一个web服务

而我们运行falsk或者django也是开启一个服务。和webdriver其实是大同小异的。

from selenium import webdriver
import requests
import time

url = "http://www.baidu.com"

driver = webdriver.Chrome(port=7005)
# driver.get(url)
"""
get方法做了哪些事情,游览器是怎么打开了百度呢?
通过源码可以看到执行了一个Command.GET,参数是我们传的url
1、self.execute(Command.GET, {‘url‘: url})
Command.GET: 就是以POST的方式向webdriver发起请求
Command.GET:(‘POST‘, ‘/session/$sessionId/url‘) 请求方法POST和地址localhost:7005
{‘url‘: url}: 参数

"""
# 利用http协议与webdriver交互,实现驱动游览器访问百度
requests.post(url=f"http://localhost:7005/session/{driver.session_id}/url", json={‘url‘: url})
time.sleep(2)
driver.close()
driver.quit()

二、make_server实现简易的基于WSGI服务的server

本次分享先抛开falsk,用python内置的wsgiref库实现的一个简易服务器。其实flask内置的服务原理也是这一套东西,这些都是本地我们本地调试时,开启的服务,实际生产环境我需要用uwsgi,ngnix等。

1、最小简易服务器实现步骤

  • 创建一个WSGI服务器:make_server(host,port,app)
  • 处理程序app方法实现:app(env,start_response)构造url 响应对象
  • 运行服务器:serve_forever() 监听动作

2、make_server(host,port,app)

  • host:ip地址,传空字符串默认localhost
  • port:端口
  • app:应用程序(application),需要定义url,构造响应对象,定义返回值。
    • env:app 与服务器如何通信的呢,其实就是通过环境变量environment,前端传输信息都会保存在里面
    • start_response: 响应对象,定义接口响应状态码,定义响应头信息
    • return:返回值到前端

3、案例:可以通游览器访问调试

from wsgiref.simple_server import make_server


def app(env, start_response):
    """
    application 应用程序
    :param env: 环境变量
    :param start_response: 响应结果,需要构造
    :return:
    """
    # 定义首页,url从边境变量里取,字段:PATH_INFO
    if env.get("PATH_INFO") == "/":
        # 构造响应对象
        start_response("200 ok", [("content-type", "text/plain")])
        return [b"hello index page"]
    elif env.get("PATH_INFO") == "/home":
        start_response("200 ok", [("content-type", "text/plain")])
        return [b"hello home page"]
    else:
        start_response("404 not found", [("content-type", "text/plain")])
        return [b"not found page"]


if __name__ == ‘__main__‘:
    # 创建server
    server = make_server(‘‘, 8005, app)
    # 永久开启
    server.serve_forever()

技术图片

4、注意:

1、 status_code 必须是一个字符串,不能是200的数字,且要4位以上

2、header 是一个元素构成的列表,不能字典

3、返回值是一个列表且要是byte类型,encode

5、如何确认服务器-application交互是通过环境变量的传输信息的

技术图片

我们只要断点debug调试即可,或者打印env查看

  • 包括本地环境变量信息
  • 包括前端请求服务器的数据都会保存环境里
    • ip、port、接口地址、host
    • 请求方法
    • 请求参数
    • 请求头
    • 以及本地配置的环境变量信息

技术图片

‘REMOTE_HOST‘ = {str} ‘‘
‘CONTENT_LENGTH‘ = {str} ‘‘
‘SCRIPT_NAME‘ = {str} ‘‘
‘SERVER_PROTOCOL‘ = {str} ‘HTTP/1.1‘
‘SERVER_SOFTWARE‘ = {str} ‘WSGIServer/0.2‘
‘REQUEST_METHOD‘ = {str} ‘GET‘
‘PATH_INFO‘ = {str} ‘/home‘
‘QUERY_STRING‘ = {str} ‘‘
‘REMOTE_ADDR‘ = {str} ‘127.0.0.1‘
‘CONTENT_TYPE‘ = {str} ‘text/plain‘
‘HTTP_HOST‘ = {str} ‘localhost:8005‘
‘HTTP_CONNECTION‘ = {str} ‘keep-alive‘
‘HTTP_PRAGMA‘ = {str} ‘no-cache‘
‘HTTP_CACHE_CONTROL‘ = {str} ‘no-cache‘
‘SERVER_PORT‘ = {str} ‘8005‘

三、application优化

当我们访问地址越来越多时,我们需要不断添加if,来判断,其他语言有switch语句,其实python有更强大的字典对象,以用映射的方法来处理,把url定义成key,
响应对象单独写成方法,value就时方法名。

此时,我们的app方法内,只需要url是不是在字典内,如果存在我们只需要调用对应的value,并返回值即可,如果不存在则直接返回定义的404的方法即可。

这样就实现了集中管理,当我们在有新的url时,我们app方法内的逻辑是不需要维护的,我们只需要添加新url方法(构造响应结果,返回值),然后添加到字典内即可。

而url和函数(构造响应对象、并返回值)组合起来就叫做路由

其实flask中也有集中注册路由的机制,内部原理也时采用的这种映射原理,只不过flask准对中小型来说实现了更为方便装饰器,只需要把url通过装饰在视图函数上即可

优化代码

from wsgiref.simple_server import make_server


# 函数实现
def home(response):
    response("200 OK", [("content-type", "text/html")])
    return "<p style=‘color:red‘>home</p>"


def project(response):
    response("200 OK", [("content-type", "text/html")])
    return "<p style=‘color:red‘>project</p>"


def interface(response):
    response("200 OK", [("content-type", "text/html")])
    return "<p style=‘color:red‘>interface</p>"


def not_found(response):
    response("404 not found", [("content-type", "text/plain"), ("charset", "UTF-8")])
    return "page not found"


# 建立映射关系
route_path = {
    "/": home,
    "/project": project,
    "/project/interface": interface

}


def app(env, response):
    """
    application 应用程序,通过映射,app基本可以保持不变
    :param env: 环境变量
    :param response: 响应结果函数,需要构造
    :return:
    """
    url = env.get("PATH_INFO")
    # 先判断不存在
    if url is None or route_path.get(url) is None:
        # 直接调用not_found()方法,返回404
        return [not_found(response).encode()]
    # 存在,调用对应url key的函数被返回
    return [route_path.get(url)(response).encode()]


if __name__ == ‘__main__‘:
    my_server = make_server(‘‘, 6005, app)
    my_server.serve_forever()

四、总结

1、app应用程序和服务器通信是通过环境变量

2、app内必须需要构造响应对象

3、 status_code 必须是一个字符串,不能是200的数字,且要4位以上

4、header 是一个元素构成的列表,不能字典

5、返回值是一个列表且要是byte类型,encode

6、可以使用字典的方式保存映射关系,达到更好管理路由。

技术图片


以上是关于Flask-0-最小原型的主要内容,如果未能解决你的问题,请参考以下文章

Flask:redirect()函数

架构师内功心法,只是单纯听说过的原型模式详解

架构师内功心法,只是单纯听说过的原型模式详解

从搜索文档中查找最小片段的算法?

Flask最小原型与唯一URl原则

Flask最小原型与唯一URl原则