mini-web框架

多进程-面向对象静态web服务器

import socket
import re
import multiprocessing


class WSGIServer(object):
    def __init__(self):
        # 1.创建套接字
        self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 2.绑定
        self.tcp_server_socket.bind(("", 7890))

        # 3.监听套接字
        self.tcp_server_socket.listen(128)

    def service_client(self, new_socket):
        """为这个客户端返回数据"""

        # 1.接收浏览器发送过来的数据,即http请求
        # GET / HTTP/1.1
        # .....
        request = new_socket.recv(1024).decode("utf-8")
        # print(">>>"*50)
        # print(request)

        request_lines = request.splitlines()
        print("")
        print(">"*20)
        print(request_lines)

        # GET/index.html HTTP/1.1
        # get post put del
        file_name = ""
        ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
        if ret:
            file_name = ret.group(1)
            # print("*"*50, file_name)
            if file_name == "/":
                file_name = "/index.html"

        # 2.返回http格式的数据,给浏览器
        try:
            f = open("./html" + file_name, "rb")
        except:
            response = "HTTP/1.1 404 NOT FOUND\r\n"
            response += "\r\n"
            response += "...file not found..."
            new_socket.send(response.encode("utf-8"))
        else:
            html_content = f.read()
            f.close()
            # 2.1 准备发送给浏览器的数据...header
            response = "HTTP/1.1 200 OK\r\n"
            response += "\r\n"
            # 2.2 准备发送给浏览器的数据...boy
            # response += "hahaha"

            # 将response header发送给浏览器
            new_socket.send(response.encode("utf-8"))
            # 将response body发送给浏览器
            new_socket.send(html_content)

        # 关闭套接字
        new_socket.close()

    def run_forever(self):
        """用来完成整体的控制"""

        while True:
            # 4.等待新客户的链接
            new_socket, client_addr = self.tcp_server_socket.accept()

            p = multiprocessing.Process(target=self.service_client, args=(new_socket,))

             # 5.为这个客户端服务
            self.service_client(new_socket)
            p.start()

            new_socket.close()

        # 关闭监听套接字
        self.tcp_server_socket.close()


def main():
    """控制整体,创建一个web服务器对象,然后调用这个对象的run_forever方法运行"""
    wsgi_server = WSGIServer()
    wsgi_server.run_forever()


if __name__ == "__main__":
    main()

多进程-面向对象web服务器,集成了解析动态请求的功能

动态web

import socket
import re
import multiprocessing
import mini_frame


class WSGIServer(object):
    def __init__(self):
        # 1.创建套接字
        self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 2.绑定
        self.tcp_server_socket.bind(("", 7890))

        # 3.监听套接字
        self.tcp_server_socket.listen(128)

    def service_client(self, new_socket):
        """为这个客户端返回数据"""

        # 1.接收浏览器发送过来的数据,即http请求
        # GET / HTTP/1.1
        # .....
        request = new_socket.recv(1024).decode("utf-8")
        # print(">>>"*50)
        # print(request)

        request_lines = request.splitlines()
        print("")
        print(">"*20)
        print(request_lines)

        # GET/index.html HTTP/1.1
        # get post put del
        file_name = ""
        ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
        if ret:
            file_name = ret.group(1)
            # print("*"*50, file_name)
            if file_name == "/":
                file_name = "/index.html"

        # 2.返回http格式的数据,给浏览器
        # 2.1 如果请求的资源不是以.py结尾,那么就认为是静态资源(html/css/js/png/,jpg等)
        if not file_name.endswith(".py"):
            try:
                f = open("./html" + file_name, "rb")
            except:
                response = "HTTP/1.1 404 NOT FOUND\r\n"
                response += "\r\n"
                response += "...file not found..."
                new_socket.send(response.encode("utf-8"))
            else:
                html_content = f.read()
                f.close()
                # 2.1 准备发送给浏览器的数据...header
                response = "HTTP/1.1 200 OK\r\n"
                response += "\r\n"
                # 2.2 准备发送给浏览器的数据...boy
                # response += "hahaha"

                # 将response header发送给浏览器
                new_socket.send(response.encode("utf-8"))
                # 将response body发送给浏览器
                new_socket.send(html_content)
        else:
            # 2.2如果是以.py结尾,那么就认为是动态资源的请求
            header = "HTTP/1.1 200 OK\r\n"
            header += "\r\n"

            # body = "hahaha %s " % time.ctime()
            # if file_name == "/login.py":
            #     body = mini_frame.login()
            # elif file_name == "register.py":
            #     body = mini_frame.register()
            body = mini_frame.application(file_name)

            response = header+body
            # 发送response给浏览器
            new_socket.send(response.encode("utf-8"))

        # 关闭套接字
        new_socket.close()

    def run_forever(self):
        """用来完成整体的控制"""

        while True:
            # 4.等待新客户的链接
            new_socket, client_addr = self.tcp_server_socket.accept()

            p = multiprocessing.Process(target=self.service_client, args=(new_socket,))

            # 5.为这个客户端服务
            self.service_client(new_socket)
            p.start()

            new_socket.close()

        # 关闭监听套接字
        self.tcp_server_socket.close()


def main():
    """控制整体,创建一个web服务器对象,然后调用这个对象的run_forever方法运行"""
    wsgi_server = WSGIServer()
    wsgi_server.run_forever()


if __name__ == "__main__":
    main()

mini_frame

import time


def login():
    return "....login...welcome to our website......time:%s" % time.ctime()


def register():
    return "....register...welcome to our website......time:%s" % time.ctime()


def profile():
    return "....profile...welcome to our website......time:%s" % time.ctime()


def application(file_name):
    if file_name == "/login.py":
        login()
    elif file_name == "/register.py":
        register()
    else:
        return "not found you page...."
def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return 'Hello World'

上面额application()函数就是符合WFGI标准的一个HTTP处理函数,它接收两个参数:

  • environ:一个包含所有HTTP请求信息的dict对象;
  • start_resp:一个发送HTTP响应的函数
    整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,把底层web服务器和应用逻辑部分进行了分离,这样开发者就可以专心做一个领域了

让web服务器支持WSGI协议

def index():
    with open("./templates/index.html") as f:
        return f.read()


def center():
    with open("./templates/center.html") as f:
        return f.read()


def application(env, start_response):
    start_response('200 OK', [('Content-Type', 'text/html;charset=utf-8')])

    file_name = env['PATH_INFO']
    # file_name = "/index.py"

    if file_name == "/index.py":
        return index()
    elif file_name == "/center.py":
        return center()
    else:
        return "Hello World 我爱你中国"
import socket
import re
import multiprocessing
import mini_frame


class WSGIServer(object):
    def __init__(self):
        # 1.创建套接字
        self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 2.绑定
        self.tcp_server_socket.bind(("", 7890))

        # 3.监听套接字
        self.tcp_server_socket.listen(128)

    def service_client(self, new_socket):
        """为这个客户端返回数据"""

        # 1.接收浏览器发送过来的数据,即http请求
        # GET / HTTP/1.1
        # .....
        request = new_socket.recv(1024).decode("utf-8")
        # print(">>>"*50)
        # print(request)

        request_lines = request.splitlines()
        print("")
        print(">"*20)
        print(request_lines)

        # GET/index.html HTTP/1.1
        # get post put del
        file_name = ""
        ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
        if ret:
            file_name = ret.group(1)
            # print("*"*50, file_name)
            if file_name == "/":
                file_name = "/index.html"

        # 2.返回http格式的数据,给浏览器
        # 2.1 如果请求的资源不是以.py结尾,那么就认为是静态资源(html/css/js/png/,jpg等)
        if not file_name.endswith(".py"):
            try:
                f = open("./html" + file_name, "rb")
            except:
                response = "HTTP/1.1 404 NOT FOUND\r\n"
                response += "\r\n"
                response += "...file not found..."
                new_socket.send(response.encode("utf-8"))
            else:
                html_content = f.read()
                f.close()
                # 2.1 准备发送给浏览器的数据...header
                response = "HTTP/1.1 200 OK\r\n"
                response += "\r\n"
                # 2.2 准备发送给浏览器的数据...boy
                # response += "hahaha"

                # 将response header发送给浏览器
                new_socket.send(response.encode("utf-8"))
                # 将response body发送给浏览器
                new_socket.send(html_content)
        else:
            # 2.2如果是以.py结尾,那么就认为是动态资源的请求

            env = dict()
            env['PATH_INFO'] = file_name
            # {"PATH_INFO":"/index.py"}
            body = mini_frame.application(env, self.set_response_header)

            header = "HTTP/1.1 %s\r\n" % self.status

            for temp in self.headers:
                header += "%s:%s\r\n" % (temp[0], temp[1])

            header += "\r\n"

            response = header+body
            # 发送response给浏览器
            new_socket.send(response.encode("utf-8"))

        # 关闭套接字
        new_socket.close()

    def set_response_header(self, status, headers):
        self.status = status
        self.headers = [("server", "mini_web v8.8")]
        self.headers += headers

    def run_forever(self):
        """用来完成整体的控制"""

        while True:
            # 4.等待新客户的链接
            new_socket, client_addr = self.tcp_server_socket.accept()

            p = multiprocessing.Process(target=self.service_client, args=(new_socket,))

            # 5.为这个客户端服务
            self.service_client(new_socket)
            p.start()

            new_socket.close()

        # 关闭监听套接字
        self.tcp_server_socket.close()


def main():
    """控制整体,创建一个web服务器对象,然后调用这个对象的run_forever方法运行"""
    wsgi_server = WSGIServer()
    wsgi_server.run_forever()


if __name__ == "__main__":
    main()

给程序传递参数,添加web服务器的配置文件

import socket
import re
import multiprocessing
# import mini_frame
import sys


class WSGIServer(object):
    def __init__(self, port, app, static_path):
        # 1.创建套接字
        self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 2.绑定
        self.tcp_server_socket.bind(("", port))

        # 3.监听套接字
        self.tcp_server_socket.listen(128)

        self.application = app
        self.static_path = static_path

    def service_client(self, new_socket):
        """为这个客户端返回数据"""

        # 1.接收浏览器发送过来的数据,即http请求
        # GET / HTTP/1.1
        # .....
        request = new_socket.recv(1024).decode("utf-8")
        # print(">>>"*50)
        # print(request)

        request_lines = request.splitlines()
        print("")
        print(">"*20)
        print(request_lines)

        # GET/index.html HTTP/1.1
        # get post put del
        file_name = ""
        ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
        if ret:
            file_name = ret.group(1)
            # print("*"*50, file_name)
            if file_name == "/":
                file_name = "/index.html"

        # 2.返回http格式的数据,给浏览器
        # 2.1 如果请求的资源不是以.py结尾,那么就认为是静态资源(html/css/js/png/,jpg等)
        if not file_name.endswith(".py"):
            try:
                f = open(self.static_path + file_name, "rb")
            except:
                response = "HTTP/1.1 404 NOT FOUND\r\n"
                response += "\r\n"
                response += "...file not found..."
                new_socket.send(response.encode("utf-8"))
            else:
                html_content = f.read()
                f.close()
                # 2.1 准备发送给浏览器的数据...header
                response = "HTTP/1.1 200 OK\r\n"
                response += "\r\n"
                # 2.2 准备发送给浏览器的数据...boy
                # response += "hahaha"

                # 将response header发送给浏览器
                new_socket.send(response.encode("utf-8"))
                # 将response body发送给浏览器
                new_socket.send(html_content)
        else:
            # 2.2如果是以.py结尾,那么就认为是动态资源的请求

            env = dict()
            env['PATH_INFO'] = file_name
            # {"PATH_INFO":"/index.py"}
            # body = mini_frame.application(env, self.set_response_header)
            body = self.application(env, self.set_response_header)

            header = "HTTP/1.1 %s\r\n" % self.status

            for temp in self.headers:
                header += "%s:%s\r\n" % (temp[0], temp[1])

            header += "\r\n"

            response = header+body
            # 发送response给浏览器
            new_socket.send(response.encode("utf-8"))

        # 关闭套接字
        new_socket.close()

    def set_response_header(self, status, headers):
        self.status = status
        self.headers = [("server", "mini_web v8.8")]
        self.headers += headers

    def run_forever(self):
        """用来完成整体的控制"""

        while True:
            # 4.等待新客户的链接
            new_socket, client_addr = self.tcp_server_socket.accept()

            p = multiprocessing.Process(target=self.service_client, args=(new_socket,))

            # 5.为这个客户端服务
            p.start()

            new_socket.close()

        # 关闭监听套接字
        self.tcp_server_socket.close()


def main():
    """控制整体,创建一个web服务器对象,然后调用这个对象的run_forever方法运行"""
    if len(sys.argv) == 3:
        try:
            port = int(sys.argv[1])  # 7890
            frame_app_name = sys.argv[2]  # mini_frame:application
        except Exception as ret:
            print("端口输入错误。。。")
            return
    else:
        print("请按照以下方式运行:")
        print("python3 xxxx.py 7890 mini_frame:application")
        return

    # mini_frame:application
    ret = re.match(r"([^:]+):(x*)", frame_app_name)
    if ret:
        frame_name = ret.group(1)  # mini_frame
        app_name = ret.group(2)  # application
    else:
        print("请按照以下方式运行:")
        print("python3 xxxx.py 7890 mini_frame:application")
        return

    with open("./web_server.conf") as f:
        conf_info = eval(f.read())

    # 此时conf_info是一个字典里面的数据为:
    # {
    #     "static_path": "./static",
    #     "dynamic_path": "./dynamic"
    # }

    sys.path.append(conf_info['dynamic_path'])

    # import frame_name --->找frame_name.py
    frame = __import__(frame_name)  # 返回值标记着 导入的这个模块
    app = getattr(frame, app_name)  # 此时app就指向了 dynamic/mini_frame模块中的application这个函数

    # print(app)

    wsgi_server = WSGIServer(port, app, conf_info['static_path'])
    wsgi_server.run_forever()


if __name__ == "__main__":
    main()

配置文件

{
    "static_path":"./static",
    "dynamic_path":"./dynamic"
}

闭包

def line_6(k, b):
    def create_y(x):
        print(k*x+b)
    return create_y

line_6_1 = line_6(1, 2)
line_6_1(0)
line_6_1(1)
line_6_1(2)

装饰器

装饰器是程序开发中经常会用到的一个功能,用好了装饰器,开发效率如虎添翼,所以这也是Python面试中必问的问题,但对于好多初次接触这个知识的人来讲,这个功能有点绕,自学时直接绕过去了,然后面试问到了就挂了,因为装饰器是程序开发的基础知识,这个都不会,别跟人家说你会Python。

#### 第一波 ####
def foo():
    print("foo")

foo  # 表示是函数
foo()  # 表示执行foo函数


#### 第二波 ####
def foo():
    print("foo")
    
    
foo = lambda x: x+1


foo()  # 执行lambda表达式,而不再是原来的foo函数,因为foo这个名字被重新指向了另外一个匿名函数

函数名仅仅是个变量,只不过指向了定义的函数而已,所以才能通过函数名()调用,如果函数名=xxx被修改了,那么当在执行函数名()时,调用的就不是之前的那个函数了

重点理解以下代码(装饰器原理)

def set_func(func):
    def call_func():
        print("---这是权限验证1---")
        print("---这是权限验证2---")
        func()
    return call_func


@set_func  # 等价于test1 = set_func(test1)
def test1():
    print("---test1---")


# ret = set_func(test1)
# ret()

# test1 = set_func(test1)
test1()

test1()

对有参数函数的装饰

def set_func(func):
    def call_func(num):
        print("---这是权限验证1---")
        print("---这是权限验证2---")
        func(num)
    return call_func


@set_func  # 等价于test1 = set_func(test1)
def test1(num):
    print("---test1---%d" % num)


test1(100)
test1(200)

对不定长参数的函数进行装饰

def set_func(func):
    print("开始进行装饰")
    def call_func(*args, **kwargs):
        print("---这是权限验证1---")
        print("---这是权限验证2---")
        # fanc(args, kwargs)  # 不行,相当于传递了2个参数:1个元组,1个字典
        func(*args, **kwargs)  # 拆包
    return call_func


@set_func  # 等价于test1 = set_func(test1)
def test1(num, *args, **kwargs):
    print("---test1---%d" % num)
    print("---test1---", args)
    print("---test1---", kwargs)


test1(100)
test1(100, 200)
test1(100, 200, 300, mm=100)

对有返回值的函数进行装饰

def set_func(func):
    print("开始进行装饰")
    def call_func(*args, **kwargs):
        print("---这是权限验证1---")
        print("---这是权限验证2---")
        # fanc(args, kwargs)  # 不行,相当于传递了2个参数:1个元组,1个字典
        return func(*args, **kwargs)  # 拆包
    return call_func


@set_func  # 等价于test1 = set_func(test1)
def test1(num, *args, **kwargs):
    print("---test1---%d" % num)
    print("---test1---", args)
    print("---test1---", kwargs)
    return "ok"


ret = test1(100)
print(ret)

多个装饰器对同一个函数进行装饰

def add_qx(func):
    print("---开始进行装饰权限1的功能---")

    def call_func(*args, **kwargs):
        print("---这是权限验证1---")
        # fanc(args, kwargs)  # 不行,相当于传递了2个参数:1个元组,1个字典
        return func(*args, **kwargs)  # 拆包

    return call_func


def add_xxx(func):
    print("---开始进行装饰权限xxx的功能---")
    def call_func(*args, **kwargs):
        print("---这是xxx的功能---")
        # fanc(args, kwargs)  # 不行,相当于传递了2个参数:1个元组,1个字典
        return func(*args, **kwargs)  # 拆包
    return call_func


@add_qx  # 等价于test1 = set_func(test1)
@add_xxx
def test1():
    print("---test1---")


test1()

先装饰下面的,执行时执行从上执行
mini-web框架_第1张图片
执行结果在这里插入图片描述

使用类当做装饰器

mini-web框架_第2张图片
执行结果
在这里插入图片描述

带有参数的装饰器

mini-web框架_第3张图片
执行结果
mini-web框架_第4张图片

元类

使用type创建类

mini-web框架_第5张图片

到底什么是元类?

mini-web框架_第6张图片

元类实现ORM

mini-web框架_第7张图片

你可能感兴趣的:(mini-web框架)