python【第十篇】自定义Web框架

源码

socket

socket服务器

import socket

sock = socket.socket()
sock.bind(('127.0.0.1', 8080))
sock.listen(5)

while True:
    conn, addr = sock.accept()
    data = conn.recv(1024)  # data为浏览器的请求(请求头+请求体)内容,类型为type(data)=bytes
    conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
    conn.send(b'hy')
    conn.close()

浏览器访问

浏览器本质是一个socket客户端

访问地址

http://127.0.0.1:8080/

请求内容(字符数为612即612字节,因此服务器一次取1024字节足够)

GET / HTTP/1.1\r\n
Host: 127.0.0.1:8080\r\n
Connection: keep-alive\r\n
Pragma: no-cache\r\n
Cache-Control: no-cache\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
Cookie: csrftoken=AmccoQlhzf9At4YXw6RGDVej7TcOCMzwvl4oR3ElSKtxlFBEBInIPSiFKGITHfrm; sessionid=elt65r87yocl51g4uiychxp46yhcyxxl; _xsrf=2|29287a7d|f4dbadc68470be9c84269330a453a416|1512198017\r\n\r\n

集成路由系统

版本一

import socket

sock = socket.socket()
sock.bind(('127.0.0.1', 8080))
sock.listen(5)


while True:
    conn, addr = sock.accept()
    data = conn.recv(1024)
    data = str(data, encoding='utf-8')
    headers, bodys = data.split('\r\n\r\n')
    print(bodys)
    temp_list = headers.split('\r\n')
    method, url, protocal = temp_list[0].split(' ')
    conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
    if url == '/':
        conn.send(b'welcome')
    else:
        conn.send(b'<h1>404 not found</h1>')

    conn.close()

 

版本二

import socket


def f1(request):
    return b'welcome'


routers = [
    ('/', f1),
]

sock = socket.socket()
sock.bind(('127.0.0.1', 8080))
sock.listen(5)

while True:
    conn, addr = sock.accept()
    data = conn.recv(8096)
    data = str(data, encoding='utf-8')
    print(data)
    headers, bodys = data.split('\r\n\r\n')

    temp_list = headers.split('\r\n')
    method, url, protocal = temp_list[0].split(' ')
    conn.send(b"HTTP/1.1 200 OK\r\n\r\n")

    func_name = None
    for item in routers:
        if item[0] == url:
            func_name = item[1]
            break

    if func_name:
        response = func_name(data)
    else:
        response = b"<h1>404 not found</h1>"

    conn.send(response)
    conn.close()

集成模板系统  

版本一:静态模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>用户登录</h1>
    <form>
        <p><input type="text" placeholder="用户名" /></p>
        <p><input type="password" placeholder="密码" /></p>
        <p><input type="submit" placeholder="提交" /></p>
    </form>
</body>
</html>
index.html
import socket


def f1(request):
    """
    处理用户请求,并返回相应的内容
    :param request: 用户请求的所有信息
    :return:
    """
    f = open('index.html', 'rb')
    data = f.read()
    f.close()
    return data


routers = [
    ('/', f1),
]

sock = socket.socket()
sock.bind(('127.0.0.1', 8080))
sock.listen(5)

while True:
    conn, addr = sock.accept()
    data = conn.recv(8096)
    data = str(data, encoding='utf-8')
    print(data)
    headers, bodys = data.split('\r\n\r\n')

    temp_list = headers.split('\r\n')
    method, url, protocal = temp_list[0].split(' ')
    conn.send(b"HTTP/1.1 200 OK\r\n\r\n")

    func_name = None
    for item in routers:
        if item[0] == url:
            func_name = item[1]
            break

    if func_name:
        response = func_name(data)
    else:
        response = b"<h1>404 not found</h1>"

    conn.send(response)
    conn.close()
View Code

版本二:动态模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <table border="1">
        <thead>
            <tr>
                <th>ID</th>
                <th>用户名</th>
                <th>邮箱</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <th>1</th>
                <th>@@hy@@</th>
                <th>root@qq.com</th>
            </tr>
        </tbody>
    </table>
</body>
</html>
article.html
import socket


def f1(request):
    """
    处理用户请求,并返回相应的内容
    :param request: 用户请求的所有信息
    :return:
    """
    f = open('index.html', 'rb')
    data = f.read()
    f.close()
    return data


def f2(request):
    f = open('article.html', 'r', encoding='utf-8')
    data = f.read()
    f.close()
    import time
    ctime = time.time()
    data = data.replace('@@hy@@', str(ctime))
    return bytes(data, encoding='utf-8')


routers = [
    ('/', f1),
    ('/article', f2),
]

sock = socket.socket()
sock.bind(('127.0.0.1', 8080))
sock.listen(5)

while True:
    conn, addr = sock.accept()
    data = conn.recv(1024)
    data = str(data, encoding='utf-8')
    print(data)
    headers, bodys = data.split('\r\n\r\n')

    temp_list = headers.split('\r\n')
    method, url, protocal = temp_list[0].split(' ')
    conn.send(b"HTTP/1.1 200 OK\r\n\r\n")

    func_name = None
    for item in routers:
        if item[0] == url:
            func_name = item[1]
            break

    if func_name:
        response = func_name(data)
    else:
        response = b"<h1>404 not found</h1>"

    conn.send(response)
    conn.close()
View Code

版本三:动态模板 + 数据库

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <table border="1">
        <thead>
            <tr>
                <th>ID</th>
                <th>用户名</th>
                <th>邮箱</th>
            </tr>
        </thead>
        <tbody>
            @@hy@@
        </tbody>
    </table>
</body>
</html>
userlist.html
import socket


def f1(request):
    """
    处理用户请求,并返回相应的内容
    :param request: 用户请求的所有信息
    :return:
    """
    f = open('index.html', 'rb')
    data = f.read()
    f.close()
    return data


def f2(request):
    f = open('article.html', 'r', encoding='utf-8')
    data = f.read()
    f.close()
    import time
    ctime = time.time()
    data = data.replace('@@hy@@', str(ctime))
    return bytes(data, encoding='utf-8')


def f3(request):
    import pymysql

    # 创建连接
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root', db='dbtest')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute("select id,username,password from userinfo")
    user_list = cursor.fetchall()
    cursor.close()
    conn.close()

    content_list = []
    for row in user_list:
        tp = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>" %(row['id'],row['username'],row['password'])
        content_list.append(tp)
    content = "".join(content_list)


    f = open('userlist.html','r',encoding='utf-8')
    template = f.read()
    f.close()

    # 模板渲染(模板+数据)
    data = template.replace('@@hy@@',content)
    return bytes(data,encoding='utf-8')

routers = [
    ('/', f1),
    ('/article', f2),
    ('/userlist', f3),
]

sock = socket.socket()
sock.bind(('127.0.0.1', 8080))
sock.listen(5)

while True:
    conn, addr = sock.accept()
    data = conn.recv(1024)
    data = str(data, encoding='utf-8')
    print(data)
    headers, bodys = data.split('\r\n\r\n')

    temp_list = headers.split('\r\n')
    method, url, protocal = temp_list[0].split(' ')
    conn.send(b"HTTP/1.1 200 OK\r\n\r\n")

    func_name = None
    for item in routers:
        if item[0] == url:
            func_name = item[1]
            break

    if func_name:
        response = func_name(data)
    else:
        response = b"<h1>404 not found</h1>"

    conn.send(response)
    conn.close()
View Code

 

版本四:动态模板+数据库+第三方模板工具

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <table border="1">
        <thead>
            <tr>
                <th>ID</th>
                <th>用户名</th>
                <th>邮箱</th>
            </tr>
        </thead>
        <tbody>
            {% for row in xxxxx %}
                <tr>
                    <td>{{row.id}}</td>
                    <td>{{row.username}}</td>
                    <td>{{row.password}}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
    {{user}}
</body>
</html>
hostlist.html
import socket


def f1(request):
    """
    处理用户请求,并返回相应的内容
    :param request: 用户请求的所有信息
    :return:
    """
    f = open('index.html', 'rb')
    data = f.read()
    f.close()
    return data


def f2(request):
    f = open('article.html', 'r', encoding='utf-8')
    data = f.read()
    f.close()
    import time
    ctime = time.time()
    data = data.replace('@@hy@@', str(ctime))
    return bytes(data, encoding='utf-8')


def f3(request):
    import pymysql

    # 创建连接
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root', db='dbtest')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute("select id,username,password from userinfo")
    user_list = cursor.fetchall()
    cursor.close()
    conn.close()

    content_list = []
    for row in user_list:
        tp = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>" % (row['id'], row['username'], row['password'])
        content_list.append(tp)
    content = "".join(content_list)

    f = open('userlist.html', 'r', encoding='utf-8')
    template = f.read()
    f.close()

    # 模板渲染(模板+数据)
    data = template.replace('@@hy@@', content)
    return bytes(data, encoding='utf-8')


def f4(request):
    import pymysql

    # 创建连接
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root', db='dbtest')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute("select id,username,password from userinfo")
    user_list = cursor.fetchall()
    cursor.close()
    conn.close()

    f = open('hostlist.html', 'r', encoding='utf-8')
    data = f.read()
    f.close()

    # 基于第三方工具实现的模板渲染
    from jinja2 import Template
    template = Template(data)
    data = template.render(xxxxx=user_list, user='ecithy')
    return data.encode('utf-8')


routers = [
    ('/', f1),
    ('/article', f2),
    ('/userlist', f3),
    ('/hostlist', f4),
]

sock = socket.socket()
sock.bind(('127.0.0.1', 8080))
sock.listen(5)

while True:
    conn, addr = sock.accept()
    data = conn.recv(1024)
    data = str(data, encoding='utf-8')
    print(data)
    headers, bodys = data.split('\r\n\r\n')

    temp_list = headers.split('\r\n')
    method, url, protocal = temp_list[0].split(' ')
    conn.send(b"HTTP/1.1 200 OK\r\n\r\n")

    func_name = None
    for item in routers:
        if item[0] == url:
            func_name = item[1]
            break

    if func_name:
        response = func_name(data)
    else:
        response = b"<h1>404 not found</h1>"

    conn.send(response)
    conn.close()
View Code

 

由于jinja2模板没有render,修改源码自定制

def render(html, **kwargs):
    f = open(html, 'r', encoding='utf-8')
    data = f.read()
    f.close()
    template = Template(data)
    data = template.render(**kwargs)
    return data.encode('utf-8')
environment.py
# 在以下两处添加render

from jinja2.environment import  render  

__all__ = [
    'render', 
]
__init__.py
import socket
import gevent
from gevent import socket, monkey

monkey.patch_all()


def f1(request):
    """
    处理用户请求,并返回相应的内容
    :param request: 用户请求的所有信息
    :return:
    """
    f = open('index.html', 'rb')
    data = f.read()
    f.close()
    return data


def f2(request):
    f = open('article.html', 'r', encoding='utf-8')
    data = f.read()
    f.close()
    import time
    ctime = time.time()
    data = data.replace('@@hy@@', str(ctime))
    return bytes(data, encoding='utf-8')


def f3(request):
    import pymysql

    # 创建连接
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root', db='dbtest')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute("select id,username,password from userinfo")
    user_list = cursor.fetchall()
    cursor.close()
    conn.close()

    content_list = []
    for row in user_list:
        tp = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>" % (row['id'], row['username'], row['password'])
        content_list.append(tp)
    content = "".join(content_list)

    f = open('userlist.html', 'r', encoding='utf-8')
    template = f.read()
    f.close()

    # 模板渲染(模板+数据)
    data = template.replace('@@hy@@', content)
    return bytes(data, encoding='utf-8')


# def render(html, **kwargs):
#     f = open(html, 'r', encoding='utf-8')
#     data = f.read()
#     f.close()
#
#     # 基于第三方工具实现的模板渲染
#     from jinja2 import Template
#     template = Template(data)
#     data = template.render(**kwargs)
#     return data.encode('utf-8')


def f4(request):
    import pymysql

    # 创建连接
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root', db='dbtest')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute("select id,username,password from userinfo")
    user_list = cursor.fetchall()
    cursor.close()
    conn.close()

    from jinja2 import render
    dict = {'xxxxx': user_list, 'user': 'ecithy'}
    return render('hostlist.html', **dict )
    # 或     eturn render('hostlist.html', xxxxx=user_list, user='ecithy')



routers = [
    ('/', f1),
    ('/article', f2),
    ('/userlist', f3),
    ('/hostlist', f4),
]


def server(port):
    sock = socket.socket()
    sock.bind(('127.0.0.1', 8080))
    sock.listen(5)

    while True:
        conn, addr = sock.accept()
        # gevent实现异步socket
        gevent.spawn(handle_request, conn)


def handle_request(conn):
    try:
        data = conn.recv(1024)
        data = str(data, encoding='utf-8')
        if not data:
            conn.shutdown(socket.SHUT_WR)
        headers, bodys = data.split('\r\n\r\n')

        temp_list = headers.split('\r\n')
        method, url, protocal = temp_list[0].split(' ')
        conn.send(b"HTTP/1.1 200 OK\r\n\r\n")

        func_name = None
        for item in routers:
            if item[0] == url:
                func_name = item[1]
                break

        if func_name:
            response = func_name(data)
        else:
            response = b"<h1>404 not found</h1>"

        conn.send(response)

    except Exception as ex:
        print(ex)

    finally:
        conn.close()


if __name__ == '__main__':
    server(8080)
View Code

版本五:动态模板+原生数据库+jinja2(自定制render)+异步socket

import socket
import gevent
from gevent import socket, monkey
from jinja2 import render

monkey.patch_all()


def f1(request):
    """
    处理用户请求,并返回相应的内容
    :param request: 用户请求的所有信息
    :return:
    """
    return render('index.html')


def f2(request):
    import time
    ctime = time.time()
    return render('article.html', hy=str(ctime))


def f3(request):
    import pymysql

    # 创建连接
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root', db='dbtest')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute("select id,username,password from userinfo")
    user_list = cursor.fetchall()
    cursor.close()
    conn.close()

    content_list = []
    for row in user_list:
        tp = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>" % (row['id'], row['username'], row['password'])
        content_list.append(tp)
    content = "".join(content_list)
    return render('userlist.html', hy=content)


def f4(request):
    import pymysql

    # 创建连接
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root', db='dbtest')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute("select id,username,password from userinfo")
    user_list = cursor.fetchall()
    cursor.close()
    conn.close()

    dict = {'xxxxx': user_list, 'user': 'ecithy'}
    return render('hostlist.html', **dict)


routers = [
    ('/', f1),
    ('/article', f2),
    ('/userlist', f3),
    ('/hostlist', f4),
]


def server(port):
    sock = socket.socket()
    sock.bind(('127.0.0.1', 8080))
    sock.listen(5)

    while True:
        conn, addr = sock.accept()
        # gevent实现异步socket
        gevent.spawn(handle_request, conn)


def handle_request(conn):
    try:
        data = conn.recv(1024)
        data = str(data, encoding='utf-8')
        if not data:
            conn.shutdown(socket.SHUT_WR)
        headers, bodys = data.split('\r\n\r\n')

        temp_list = headers.split('\r\n')
        method, url, protocal = temp_list[0].split(' ')
        conn.send(b"HTTP/1.1 200 OK\r\n\r\n")

        func_name = None
        for item in routers:
            if item[0] == url:
                func_name = item[1]
                break

        if func_name:
            response = func_name(data)
        else:
            response = b"<h1>404 not found</h1>"

        conn.send(response)

    except Exception as ex:
        print(ex)

    finally:
        conn.close()


if __name__ == '__main__':
    server(8080)
View Code

集成orm

# coding:utf-8 
__author__ = 'hy'
from sqlalchemy import Column, Integer, String, create_engine, UniqueConstraint
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/dbtest?charset=utf8", max_overflow=5)
Base = declarative_base()


class User(Base):
    # 表的名字:
    __tablename__ = 'user'

    # 表的结构:
    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(32))
    password = Column(String(32))

    __table_args__ = (
        UniqueConstraint('username', 'password', name='uix_id_name'),
    )


def init_table():
    '''
    创建表
    :return:
    '''
    Base.metadata.create_all(engine)


def drop_table():
    '''
    删除表
    :return:
    '''
    Base.metadata.drop_all(engine)
models.py
import socket
import gevent
from gevent import socket, monkey
from jinja2 import render
from models import User, engine, sessionmaker
# from sqlalchemy.orm import sessionmaker

monkey.patch_all()


def f1(request):
    """
    处理用户请求,并返回相应的内容
    :param request: 用户请求的所有信息
    :return:
    """
    return render('index.html')


def f2(request):
    import time
    ctime = time.time()
    return render('article.html', hy=str(ctime))


def f3(request):
    import pymysql

    # 创建连接
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root', db='dbtest')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute("select id,username,password from userinfo")
    user_list = cursor.fetchall()
    cursor.close()
    conn.close()

    content_list = []
    for row in user_list:
        tp = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>" % (row['id'], row['username'], row['password'])
        content_list.append(tp)
    content = "".join(content_list)
    return render('userlist.html', hy=content)


def objs_to_dicts(objs):
    '''把对象列表转换为字典列表'''
    obj_arr = []

    for obj in objs:
        # 把Object对象转换成Dict对象
        dict = {}
        dict.update(obj.__dict__)
        obj_arr.append(dict)

    return obj_arr


def f4(request):
    Session = sessionmaker(bind=engine)
    session = Session()

    user_list = session.query(User).all()
    user_list = objs_to_dicts(user_list)

    session.commit()
    session.close()

    dict = {'xxxxx': user_list, 'user': 'ecithy'}
    return render('hostlist.html', **dict)


routers = [
    ('/', f1),
    ('/article', f2),
    ('/userlist', f3),
    ('/hostlist', f4),
]


def server(port):
    sock = socket.socket()
    sock.bind(('127.0.0.1', 8080))
    sock.listen(5)

    while True:
        conn, addr = sock.accept()
        # gevent实现异步socket
        gevent.spawn(handle_request, conn)


def handle_request(conn):
    try:
        data = conn.recv(1024)
        data = str(data, encoding='utf-8')
        if not data:
            conn.shutdown(socket.SHUT_WR)
        headers, bodys = data.split('\r\n\r\n')

        temp_list = headers.split('\r\n')
        method, url, protocal = temp_list[0].split(' ')
        conn.send(b"HTTP/1.1 200 OK\r\n\r\n")

        func_name = None
        for item in routers:
            if item[0] == url:
                func_name = item[1]
                break

        if func_name:
            response = func_name(data)
        else:
            response = b"<h1>404 not found</h1>"

        conn.send(response)

    except Exception as ex:
        print(ex)

    finally:
        conn.close()


if __name__ == '__main__':
    server(8080)
View Code 

  

 

 

  

 

posted @ 2017-02-27 14:38  沐风先生  阅读(530)  评论(0编辑  收藏  举报