• python网络之web框架


    逐步引入:

    1. 最简单的web server

    #!/usr/bin/env python
    # coding:utf-8
    
    import socket
    
    sk = socket.socket()
    
    sk.bind(("127.0.0.1", 8000))
    
    sk.listen()
    
    while 1:
        conn, _ = sk.accept()  # py中使用单下划线代表没有用到的变量
    
        data = conn.recv(8096)
    
        print(data)
    
        conn.send(b'http/1.1 200 OK
    content-type:text/html; charset=utf-8
    
    ')
        conn.send(b'<h2>Hello,world.</h2>')
    
        conn.close()
        sk.close()
    
    
    # 以上是所有浏览器的本质

    2.不同路径的响应:

    #!/usr/bin/env python
    # coding:utf-8
    
    import socket
    
    sk = socket.socket()
    
    sk.bind(("127.0.0.1", 8000))
    
    sk.listen()
    
    # 写一个死循环,一直等待客户端来连我
    while 1:
        # 获取与客户端的连接
        conn, _ = sk.accept()
        # 接收客户端发来消息
        data = conn.recv(8096)
        # 把收到的数据转成字符串类型
        data_str = str(data, encoding="utf-8")  # bytes("str", enconding="utf-8")
        # print(data_str)
        # 用
    去切割上面的字符串
        l1 = data_str.split("
    ")
        # print(l1[0])
        # 按照空格切割上面的字符串
        l2 = l1[0].split()
        url = l2[1]
        # 给客户端回复消息
        conn.send(b'http/1.1 200 OK
    content-type:text/html; charset=utf-8
    
    ')
        # 想让浏览器在页面上显示出来的内容都是响应正文
    
        # 根据不同的url返回不同的内容
        if url == "/yimi/":
            response = b'<h1>hello yimi!</h1>'
        elif url == "/xiaohei/":
            response = b'<h1>hello xiaohei!</h1>'
        else:
            response = b'<h1>404! not found!</h1>'
        conn.send(response)
        # 关闭
        conn.close()
        # sk.close()

    3.函数版server

    #!/usr/bin/env python
    # coding:utf-8
    
    """
    完善的web服务端示例
    函数版根据不同的路径返回不同的内容
    """
    
    import socket
    
    # 生成socket实例对象
    sk = socket.socket()
    # 绑定IP和端口
    sk.bind(("127.0.0.1", 8001))
    # 监听
    sk.listen()
    
    # 定义一个处理/yimi/的函数
    def yimi(url):
        ret = 'hello {}'.format(url)
        return bytes(ret, encoding="utf-8")
    
    
    # 定义一个处理/xiaohei/的函数
    def xiaohei(url):
        ret = '你好。 {}'.format(url)
        return bytes(ret, encoding="utf-8")
    
    
    # 写一个死循环,一直等待客户端来连我
    while 1:
        # 获取与客户端的连接
        conn, _ = sk.accept()
        # 接收客户端发来消息
        data = conn.recv(8096)
        # 把收到的数据转成字符串类型
        data_str = str(data, encoding="utf-8")  # bytes("str", enconding="utf-8")
        # print(data_str)
        # 用
    去切割上面的字符串
        l1 = data_str.split("
    ")
        # print(l1[0])
        # 按照空格切割上面的字符串
        l2 = l1[0].split()
        url = l2[1]
        # 给客户端回复消息
        conn.send(b'http/1.1 200 OK
    content-type:text/html; charset=utf-8
    
    ')
        # 想让浏览器在页面上显示出来的内容都是响应正文
    
        # 根据不同的url返回不同的内容
        if url == "/yimi/":
            response = yimi(url)
        elif url == "/xiaohei/":
            response = xiaohei(url)
        else:
            response = b'<h1>404! not found!</h1>'
        conn.send(response)
        # 关闭
        conn.close()

    4.进阶版server

    #!/usr/bin/env python
    # coding:utf-8
    
    """
    完善的web服务端示例
    函数版根据不同的路径返回不同的内容
    进阶函数版 不写if判断了,用url名字去找对应的函数名
    """
    
    import socket
    
    # 生成socket实例对象
    sk = socket.socket()
    # 绑定IP和端口
    sk.bind(("127.0.0.1", 8001))
    # 监听
    sk.listen()
    
    # 定义一个处理/yimi/的函数
    def yimi(url):
        ret = 'hello {}'.format(url)
        return bytes(ret, encoding="utf-8")
    
    
    # 定义一个处理/xiaohei/的函数
    def xiaohei(url):
        ret = 'hello {}'.format(url)
        return bytes(ret, encoding="utf-8")
    
    
    # 定义一个专门用来处理404的函数
    def f404(url):
        ret = "你访问的这个{} 找不到".format(url)
        return bytes(ret, encoding="utf-8")
    
    
    url_func = [
        ("/yimi/", yimi),
        ("/xiaohei/", xiaohei),
    ]
    
    
    # 写一个死循环,一直等待客户端来连我
    while 1:
        # 获取与客户端的连接
        conn, _ = sk.accept()
        # 接收客户端发来消息
        data = conn.recv(8096)
        # 把收到的数据转成字符串类型
        data_str = str(data, encoding="utf-8")  # bytes("str", enconding="utf-8")
        # print(data_str)
        # 用
    去切割上面的字符串
        l1 = data_str.split("
    ")
        # print(l1[0])
        # 按照空格切割上面的字符串
        l2 = l1[0].split()
        url = l2[1]
        # 给客户端回复消息
        conn.send(b'http/1.1 200 OK
    content-type:text/html; charset=utf-8
    
    ')
        # 想让浏览器在页面上显示出来的内容都是响应正文
    
        # 根据不同的url返回不同的内容
        # 去url_func里面找对应关系
        for i in url_func:
            if i[0] == url:
                func = i[1]
                break
        # 找不到对应关系就默认执行f404函数
        else:
            func = f404
        # 拿到函数的执行结果
        response = func(url)
        # 将函数返回的结果发送给浏览器
        conn.send(response)
        # 关闭连接
        conn.close()

    5.返回动态html   其中yimi.html中有个内容是:<p>@@xx@@</p>  在响应时将被先替换再返回

    """
    完善的web服务端示例
    函数版根据不同的路径返回不同的内容
    进阶函数版 不写if判断了,用url名字去找对应的函数名
    返回html页面
    返回动态的html页面
    """
    
    import socket
    
    # 生成socket实例对象
    sk = socket.socket()
    # 绑定IP和端口
    sk.bind(("127.0.0.1", 8001))
    # 监听
    sk.listen()
    
    # 定义一个处理/yimi/的函数
    def yimi(url):
        with open("yimi.html", "r", encoding="utf-8") as f:
           ret = f.read()
        import time
        # 得到替换后的字符串
        ret2 = ret.replace("@@xx@@", str(time.time()))
        return bytes(ret2, encoding="utf-8")
    
    
    # 定义一个处理/xiaohei/的函数
    def xiaohei(url):
        with open("xiaohei.html", "rb") as f:
           ret = f.read()
        return ret
    
    
    # 定义一个专门用来处理404的函数
    def f404(url):
        ret = "你访问的这个{} 找不到".format(url)
        return bytes(ret, encoding="utf-8")
    
    
    url_func = [
        ("/yimi/", yimi),
        ("/xiaohei/", xiaohei),
    ]
    
    
    # 写一个死循环,一直等待客户端来连我
    while 1:
        # 获取与客户端的连接
        conn, _ = sk.accept()
        # 接收客户端发来消息
        data = conn.recv(8096)
        # 把收到的数据转成字符串类型
        data_str = str(data, encoding="utf-8")  # bytes("str", enconding="utf-8")
        # print(data_str)
        # 用
    去切割上面的字符串
        l1 = data_str.split("
    ")
        # print(l1[0])
        # 按照空格切割上面的字符串
        l2 = l1[0].split()
        url = l2[1]
        # 给客户端回复消息
        conn.send(b'http/1.1 200 OK
    content-type:text/html; charset=utf-8
    
    ')
        # 想让浏览器在页面上显示出来的内容都是响应正文
    
        # 根据不同的url返回不同的内容
        # 去url_func里面找对应关系
        for i in url_func:
            if i[0] == url:
                func = i[1]
                break
        # 找不到对应关系就默认执行f404函数
        else:
            func = f404
        # 拿到函数的执行结果
        response = func(url)
        # 将函数返回的结果发送给浏览器
        conn.send(response)
        # 关闭连接
        conn.close()

    6.使用wsgiref模块

    """
    根据URL中不同的路径返回不同的内容--函数进阶版
    返回HTML页面
    让网页动态起来
    wsgiref模块版
    """
    
    import time
    from wsgiref.simple_server import make_server
    
    
    # 将返回不同的内容部分封装成函数
    def yimi(url):
        with open("yimi.html", "r", encoding="utf8") as f:
            s = f.read()
            now = str(time.time())
            s = s.replace("@@xx@@", now)
        return bytes(s, encoding="utf8")
    
    
    def xiaohei(url):
        with open("xiaohei.html", "r", encoding="utf8") as f:
            s = f.read()
        return bytes(s, encoding="utf8")
    
    
    # 定义一个url和实际要执行的函数的对应关系
    list1 = [
        ("/yimi/", yimi),
        ("/xiaohei/", xiaohei),
    ]
    
    
    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()

    7.使用jinja2

    from wsgiref.simple_server import make_server
    from jinja2 import Template
    
    
    def index():
        with open("jinja2test.html", "r", encoding="utf-8") as f:
            data = f.read()
        template = Template(data)  # 生成模板文件
        # 从数据库中取数据
        import pymysql
    
        conn = pymysql.connect(
            host="192.168.112.13",
            port=3306,
            user="root",
            password="123456",
            database="test",
            charset="utf8",
        )
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        cursor.execute("select * from users;")
        user_list = cursor.fetchall()
        # 实现字符串的替换
        ret = template.render({"user_list": user_list})  # 把数据填充到模板里面
        return [bytes(ret, encoding="utf8"), ]
    
    
    def home():
        with open("home.html", "rb") as f:
            data = f.read()
        return [data, ]
    
    
    # 定义一个url和函数的对应关系
    URL_LIST = [
        ("/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 URL_LIST:
            if i[0] == url:
                func = i[1]  # 去之前定义好的url列表里找url应该执行的函数
                break
        if func:  # 如果能找到要执行的函数
            return func()  # 返回函数的执行结果
        else:
            return [bytes("404没有该页面", encoding="utf8"), ]
    
    
    if __name__ == '__main__':
        httpd = make_server('', 8000, run_server)
        print("Serving HTTP on port 8000...")
        httpd.serve_forever()

    其中jinja2test.html内容:

    <!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>
    
    
    <table border="1">
        <thead>
        <tr>
            <th>ID</th>
            <th>用户名</th>
            <th>性别</th>
            <th>年龄</th>
            <th>部门</th>
        </tr>
        </thead>
        <tbody>
        {% for user in user_list %}
        <tr>
            <td>{{user.sno}}</td>
            <td>{{user.sname}}</td>
            <td>{{user.sgender}}</td>
            <td>{{user.sage}}</td>
            <td>{{user.sdept}}</td>
        </tr>
        {% endfor %}
        </tbody>
    </table>
    </body>
    </html>
  • 相关阅读:
    Symmetric Order
    Red and Black
    Sticks(递归经典)
    Pascal Library
    cantor的数表
    OJ 调试技巧:VS2010 中 通过设置编译参数定义宏,无需修改源文件重定向标准输入输出
    strcmp
    最短周期串
    字母重排
    codeblocks 单步调试
  • 原文地址:https://www.cnblogs.com/frx9527/p/python_http.html
Copyright © 2020-2023  润新知