Python笔记16(Web框架本质)

一、SocketServer实例

我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端。 这样我们就可以自己实现Web框架了。

我们的Web server在给客户端回复消息的时候按照HTTP协议的规则加上响应状态行,这样我们就实现了一个正经的Web框架了。

1、不同的路径返回不同的内容

import socket

sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.listen()

while 1:
    conn, addr = sk.accept()
    # 接收消息
    data = conn.recv(8000)
    # print(data)
    # 把字节类型的数据转换成字符串
    data_str = str(data, encoding="utf8")
    # 将收到的消息按照
分割,得到第一行
    first_line = data_str.split("
")[0]
    # 对第一行按照空格分
    url = first_line.split()[1]
    print(url)
    # 根据用户访问的路径返回不同的内容
    if url == "/index/":
        msg = b'index'
    elif url == "/home/":
        msg = b'home'
    else:
        msg = b'404 not found'
    # 回复消息
    # 按照约定好的格式回复消息
    conn.send(b'http/1.1 200 ok

')
    conn.send(msg)
    conn.close()

2、函数版

import socket

sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.listen()

# 定义一个专门用来处理访问index的函数
def index():
    with open('index.html', 'rb') as f:
        data = f.read()
    return data

def home():
    return b'home'

# 定义一个访问路径和将要执行的函数的对应关系
url_func = [
    ('/index/', index),
    ('/home/', home),
]

while 1:
    conn, addr = sk.accept()
    # 接收消息
    data = conn.recv(8000)
    # print(data)
    # 把字节类型的数据转换成字符串
    data_str = str(data, encoding="utf8")
    # 将收到的消息按照
分割,得到第一行
    first_line = data_str.split("
")[0]
    # 对第一行按照空格分
    url = first_line.split()[1]
    print(url)
    # 根据用户访问的路径返回不同的内容
    for i in url_func:
        if i[0] == url:
            func = i[1]
            break
    else:
        func = None
    if func:
        msg = func()
    else:
        msg = b'404 not found!'

    # 回复消息
    # 按照约定好的格式回复消息
    conn.send(b'http/1.1 200 ok

')
    conn.send(msg)
    conn.close()

3、动态页面

import socket

sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.listen()

# 定义一个专门用来处理访问index的函数
def index():
    with open('index.html', 'r', encoding='utf8') as f:
        data = f.read()
    import time
    now = str(time.time())
    data_s = data.replace('@@XX@@', now)
    return bytes(data_s, encoding='utf8')

def home():
    return b'home'

# 定义一个访问路径和将要执行的函数的对应关系
url_func = [
    ('/index/', index),
    ('/home/', home),
]

while 1:
    conn, addr = sk.accept()
    # 接收消息
    data = conn.recv(8000)
    # print(data)
    # 把字节类型的数据转换成字符串
    data_str = str(data, encoding="utf8")
    # 将收到的消息按照
分割,得到第一行
    first_line = data_str.split("
")[0]
    # 对第一行按照空格分
    url = first_line.split()[1]
    print(url)
    # 根据用户访问的路径返回不同的内容
    for i in url_func:
        if i[0] == url:
            func = i[1]
            break
    else:
        func = None
    if func:
        msg = func()
    else:
        msg = b'404 not found!'

    # 回复消息
    # 按照约定好的格式回复消息
    conn.send(b'http/1.1 200 ok

')
    conn.send(msg)
    conn.close()

二、总结

1、HTTP协议:

1)请求(request)
2) 响应(response)

2、web框架本质

0)socket收发消息
1)访问不同的URL返回不同的页面
用户访问的具体路径 --> 执行不同的函数 --> 返回不同的结果
2)不同用户访问相同的URL返回不同的页面内容
字符串的替换


3、Web框架的本质三大部分:

a. 收发socket消息 (web服务器 、web应用程序)
b. 根据不同的请求执行不同的函数返回不同的内容
c. 字符串替换

Django开发阶段使用 wsgiref 模块来处理socket消息
Django部署到线上使用 uWsgi/gunicorn 模块来处理socket消息

Python中 web服务器程序和Web应用程序之间传递消息:WSGI协议

Python里面Web框架的分类:
1)自己实现b和c,使用第三方的a:
Django框架
2)自己实现b,使用第三方的a和c:
Flask框架
3)自己实现ac:
Tornado框架

三、服务器程序和应用程序

对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。

服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。

应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。

这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。

这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

WSGI(Web Server Gateway Interface)就是一种规范,它定义了使用Python编写的web应用程序与web服务器程序之间的接口格式,实现web应用程序与web服务器程序间的解耦。

常用的WSGI服务器有uwsgi、Gunicorn。而Python标准库提供的独立WSGI服务器叫wsgiref,Django开发环境用的就是这个模块来做服务器。

我们利用wsgiref模块来替换我们自己写的web框架的socket server部分:

"""
根据URL中不同的路径返回不同的内容--函数进阶版
返回HTML页面
让网页动态起来
wsgiref模块版
"""

import time
from wsgiref.simple_server import make_server

# 将返回不同的内容部分封装成函数
def index(url):
    with open("index.html", "r", encoding="utf8") as f:
        s = f.read()
        now = str(time.time())
        s = s.replace("@@oo@@", now)
    return bytes(s, encoding="utf8")

def home(url):
    with open("home.html", "r", encoding="utf8") as f:
        s = f.read()
    return bytes(s, encoding="utf8")

# 定义一个url和实际要执行的函数的对应关系
list1 = [
    ("/index/", index),
    ("/home/", home),
]

def run_server(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ])  # 设置HTTP响应的状态码和头信息
    url = environ['PATH_INFO']  # 取到用户输入的url
    func = None
    for i in list1:
        if i[0] == url:
            func = i[1]
            break
    if func:
        response = func(url)
    else:
        response = b"404 not found!"
    return [response, ]

if __name__ == '__main__':
    httpd = make_server('127.0.0.1', 8090, run_server)
    print("我在8090等你哦...")
    httpd.serve_forever()
原文地址:https://www.cnblogs.com/xingye-mdd/p/9444586.html