浅谈 Web框架

一、Web框架本质

  • 所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端

二、Web框架功能

  • socket收发消息 —— wsgiref(测试)、uwsgi(线上)

  • 根据不同的路径返回不同的字符串

  • 返回动态页面(字符串的替换)—— jinja2

三、Web框架种类

  • django

    • 根据不同的路径返回不同的字符串

    • 返回动态页面(字符串的替换)

  • flask

    • 根据不同的路径返回不同的字符串

  • tornado

    • socket收发消息

    • 根据不同的路径返回不同的字符串

    • 返回动态页面(字符串的替换)

四、自定义web框架

  • 简单示例:socket服务端

    import socket
    # 创建一个socket对象
    sk = socket.socket()
    # 绑定IP和端口
    sk.bind(('127.0.0.1', 8000))
    # 监听
    sk.listen(5)
    # 等待连接
    while True:
        conn, addr = sk.accept()
        # 接收数据
        data= conn.recv(1024)
        print(data)
        # 返回数据
        conn.send(b'HTTP/1.1 200 OK\r\n\r\n<h1>ok!</h1>')
        # 断开连接
        conn.close()
  • 根据不同路径返回不同的内容(普通版)

    import socket
    # 创建一个socket对象
    sk = socket.socket()
    # 绑定IP和端口
    sk.bind(('127.0.0.1', 8000))
    # 监听
    sk.listen(5)
    # 等待连接
    while True:
        conn, addr = sk.accept()
        # 接收数据
        data = conn.recv(1024)
        data = data.decode('utf-8')
        url = data.split()[1]
        conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
        if url == '/index/':
            # 返回数据
            conn.send(b'<h1>index!</h1>')
        elif url == '/home/':
            conn.send(b'<h1>home!</h1>')
        else:
            conn.send(b'<h1>404 not found!</h1>')
        # 断开连接
        conn.close()
    普通版
    import socket
    # 创建一个socket对象
    sk = socket.socket()
    # 绑定IP和端口
    sk.bind(('127.0.0.1', 8000))
    # 监听
    sk.listen(5)
    # 函数
    def index(url):
        ret = '<h1>index!</h1>({})'.format(url)
        return ret.encode('utf-8')
    def home(url):
        ret = '<h1>home!</h1>({})'.format(url)
        return ret.encode('utf-8')
    # 等待连接
    while True:
        conn, addr = sk.accept()
        # 接收数据
        data = conn.recv(1024)
        data = data.decode('utf-8')
        url = data.split()[1]
        conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
        if url == '/index/':
            # 返回数据
            ret = index(url)
        elif url == '/home/':
            ret = home(url)
        else:
            ret = b'<h1>404 not found!</h1>'
        conn.send(ret)
        # 断开连接
        conn.close()
    函数版
    import socket
    # 创建一个socket对象
    sk = socket.socket()
    # 绑定IP和端口
    sk.bind(('127.0.0.1', 8000))
    # 监听
    sk.listen(5)
    # 函数
    def index(url):
        ret = '<h1>index!</h1>({})'.format(url)
        return ret.encode('utf-8')
    def home(url):
        ret = '<h1>home!</h1>({})'.format(url)
        return ret.encode('utf-8')
    # 定义一个list1和实际要执行的函数的对应关系 
    list1 = [
        ('/index/', index),
        ('/home/', home),
    ]
    # 等待连接
    while True:
        conn, addr = sk.accept()
        # 接收数据
        data = conn.recv(1024)
        data = data.decode('utf-8')
        url = data.split()[1]
        conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
        func = None
        for i in list1:
            if url == i[0]:
                func = i[1]
                break
        if func:
            ret = func(url)
        else:
            ret = b'<h1>404 not found!</h1>'
        conn.send(ret)
        # 断开连接
        conn.close()
    函数进阶版
    import socket
    # 创建一个socket对象
    sk = socket.socket()
    # 绑定IP和端口
    sk.bind(('127.0.0.1', 8000))
    # 监听
    sk.listen(5)
    # 函数
    def index(url):
        with open('index.html','rb') as f:
            ret = f.read()
        return ret
    def home(url):
        ret = '<h1>home!</h1>({})'.format(url)
        return ret.encode('utf-8')
    # 定义一个list1和实际要执行的函数的对应关系
    list1 = [
        ('/index/', index),
        ('/home/', home),
    ]
    # 等待连接
    while True:
        conn, addr = sk.accept()
        # 接收数据
        data = conn.recv(1024)
        data = data.decode('utf-8')
        url = data.split()[1]
        conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
        func = None
        for i in list1:
            if url == i[0]:
                func = i[1]
                break
        if func:
            ret = func(url)
        else:
            ret = b'<h1>404 not found!</h1>'
        conn.send(ret)
        # 断开连接
        conn.close()
    返回html页面
    import socket
    import time
    # 创建一个socket对象
    sk = socket.socket()
    # 绑定IP和端口
    sk.bind(('127.0.0.1', 8000))
    # 监听
    sk.listen(5)
    # 函数
    def index(url):
        with open('index.html', 'rb') as f:
            ret = f.read()
        return ret
    def home(url):
        ret = '<h1>home!</h1>({})'.format(url)
        return ret.encode('utf-8')
    def timer(url):
        now = time.strftime('%H:%M:%S')
        with open('time.html','r',encoding='utf-8') as f:
            data = f.read()
        data = data.replace('xxtimexx',now)
    ​
        return data.encode('utf-8')
    # 定义一个list1和实际要执行的函数的对应关系
    list1 = [
        ('/index/', index),
        ('/home/', home),
        ('/time/', timer),
    ]
    # 等待连接
    while True:
        conn, addr = sk.accept()
        # 接收数据
        data = conn.recv(1024)
        data = data.decode('utf-8')
        url = data.split()[1]
        conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
        func = None
        for i in list1:
            if url == i[0]:
                func = i[1]
                break
        if func:
            ret = func(url)
        else:
            ret = b'<h1>404 not found!</h1>'
        conn.send(ret)
        # 断开连接
        conn.close()
    补充:time.html
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>当前时间是:@@time@@</h1>
    </body>
    </html>
    返回动态页面

五、wsgiref

  • 常用的WSGI服务器有uWSGI、Gunicorn

    • Python标准库提供的独立WSGI服务器叫wsgiref,Django开发环境用的就是这个模块来做服务器

  • 简单示例:

    """  
    根据URL中不同的路径返回不同的内容--函数进阶版  
    返回HTML页面  
    让网页动态起来  
    wsgiref模块版  
    """       
    from wsgiref.simple_server import make_server     
        
    # 将返回不同的内容部分封装成函数   
    def index(url):   
        # 读取index.html页面的内容   
        with open("index.html", "r", encoding="utf8") as f:   
            s = f.read()   
        # 返回字节数据   
        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")       
         
    def timer(url):   
        import time   
        with open("time.html", "r", encoding="utf8") as f:   
            s = f.read()   
            s = s.replace('@@time@@', time.strftime("%Y-%m-%d %H:%M:%S"))   
        return bytes(s, encoding="utf8")        
         
    # 定义一个url和实际要执行的函数的对应关系   
    list1 = [   
        ("/index/", index),   
        ("/home/", home),   
        ("/time/", timer),   
    ]        
         
    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()  
    示例

六、jinja2

  1. 模板渲染现成的工具:jinja2

    • 下载jinja2:pip install jinja2

  2. 示例:

    from wsgiref.simple_server import make_server  
    from jinja2 import Template    
      
    def index(url):  
        # 读取HTML文件内容  
        with open("index2.html", "r", encoding="utf8") as f:  
            data = f.read()  
            template = Template(data)   # 生成模板文件 
            ret = template.render({'name': 'alex', 'hobby_list': ['抽烟', '喝酒', '烫头']})   # 把数据填充到模板中  
        return bytes(ret, 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() 
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Title</title>
    </head>
    <body>
        <h1>姓名:{{name}}</h1>
        <h1>爱好:</h1>
        <ul>
            {% for hobby in hobby_list %}
                <li>{{hobby}}</li>
            {% endfor %}
        </ul>
    </body>
    </html>
    index2.html
posted @ 2019-08-09 18:08  林染  阅读(842)  评论(1编辑  收藏  举报