Python基础-30-动态服务器

多进程面向对象服务器

这是一个静态服务器

  • 通过正则得到请求的url
  • 然后找到这个url对应的文件,把文件内容读取后返回给浏览器
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 FOUNDrn"
            response += "rn"
            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 OKrn"
            response += "rn"
            # 2.2 准备发送给浏览器的数据---boy
            # response += "hahahhah"

            # 将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()

            # 5. 为这个客户端服务
            p = multiprocessing.Process(target=self.service_client, args=(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()

多进程面向对象的动态服务器

  • 这里是根据正则得到的url中的请求
  • 如果是.py结尾的,就动态返回当前时间
  • 否则,就返回指定页面的内容
  • 这里的程序有一个缺点:这是一个服务器,它集成了解析动态请求的功能,应该根据动态和静态去请求一个web框架,让web框架来返回动态信息
import socket
import re
import multiprocessing
import time


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 FOUNDrn"
                response += "rn"
                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 OKrn"
                response += "rn"
                # 2.2 准备发送给浏览器的数据---boy
                # response += "hahahhah"

                # 将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 OKrn"
            header += "rn" # 这里必须增加一个换行,是响应体决定的

            body = "hahahah %s " % time.ctime()

            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()

            # 5. 为这个客户端服务
            p = multiprocessing.Process(target=self.service_client, args=(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服务器和逻辑处理的代码分开

  • mini_freame.py是中是一个方法,其返回值作为web服务器的响应体
  • web服务器中,根据.py的名称,动态去请求mini_freame.py中的方法
  • 该方式的缺点
  • 在web服务器中,需要根据 if-elif来判断需要请求mini_freame.py中的哪个方法
  • 解耦不够明显

定义一个框架mini_freame.py

  • 给框架就是一个返回不同内容的框架
  • 共服务器来调用使用
import time

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

def register():
    return "register success"

web服务器

  • 该web服务器,根据带.py结尾的请求不同,去请求mini_freame.py中的不同方法,把其返回值当做body返回给浏览器
  • 注意:这里需要在web服务器中判断,需要请求mini_freame.py中哪个方法
import socket
import re
import multiprocessing
import time
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 FOUNDrn"
                response += "rn"
                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 OKrn"
                response += "rn"
                # 2.2 准备发送给浏览器的数据---boy
                # response += "hahahhah"

                # 将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 OKrn"
            header += "rn"

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

            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()

            # 5. 为这个客户端服务
            p = multiprocessing.Process(target=self.service_client, args=(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服务器和逻辑处理的代码分开-升级版

  • 解决上一个版本的解耦不够彻底的问题

mini_freame.py

  • 在该版本的框架中,有一个application方法,其参数就是需要请求的.py的请求
import time

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

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

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

def application(file_name):
 if file_name == "/login.py":
  return login()
 elif file_name == "/register.py":
  return register()
 else:
  return "not found you page...."

web服务器

  • 在当前服务器版本中,只需要调用mini_freame.py中的application方法,传递当前的.py结尾的文件名即可
  • mini_freame.py中的application方法根据其参数来处理请求即可
import socket
import re
import multiprocessing
import time
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 FOUNDrn"
                response += "rn"
                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 OKrn"
                response += "rn"
                # 2.2 准备发送给浏览器的数据---boy
                # response += "hahahhah"

                # 将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 OKrn"
            header += "rn"

            # body = "hahahah %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()

            # 5. 为这个客户端服务
            p = multiprocessing.Process(target=self.service_client, args=(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()

WSGI

我们写的框架,如何与现有的开源服务器结合

  • 当我们写好了框架后,可以自己实现服务器来与该框架结合,但是自己写的服务器不一定能支持大量并发
  • 如果使用nginx等开源服务器的话,那nginx也不知道应该调用我们框架中的哪些方法呢,并且nginx服务器也不知道如何引用我们的框架呢
  • 这个就需要python的Web Server Gateway Interface (或简称 WSGI,读作“wizgy”)

WSGI

  • WSGI可以让框架与服务器协同工作
  • WSGI允许开发者将选择web框架和web服务器分开。
  • 可以混合匹配web服务器和web框架,选择一个适合的配对。
  • 比如,可以在Gunicorn 或者 Nginx/uWSGI 或者 Waitress上运行 Django, Flask, 或 Pyramid。
  • 真正的混合匹配,得益于WSGI同时支持服务器和架构

web服务器必须具备WSGI接口

  • 所有的现代Python Web框架都已具备WSGI接口,它让你不对代码作修改就能使服务器和特点的web框架协同工作。

定义WSGI接口

  • WSGI接口定义非常简单,它只要求Web开发者实现一个函数,就可以响应HTTP请求
  • 函数如下
def application(environ, set_response_header):
    start_response('200 OK', [('Content-Type''text/html')])
    return 'Hello World!'
  • 上面的application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数
  • environ:一个包含所有HTTP请求信息的dict对象;
  • set_response_header:一个发送HTTP响应的函数(这个方法不一定就是这个,这里是为了说明用法)。
  • set_response_header方法是需要两个参数,第一个参数是状态码,第二个参数就是响应头,是一个列表,里面存的是元组,可以有多个元组
  • 整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,把底层web服务器解析部分和应用程序逻辑部分进行了分离,这样开发者就可以专心做一个领域了
  • application()函数必须由WSGI服务器调用
  • application()函数的返回值就是body

浏览器请求动态页面过程

  • 当浏览器请求到实现了WSGI的服务器时,服务器就会去调用框架的application()函数,并且传递两个参数environset_response_header
  • environ是HTTP请求对象的dict字典
  • set_response_header是让框架调用服务器中,设置响应头的回调函数
  • 框架会去调用服务器传递过来的第二个参数回调函数,把响应头给服务器,返回到框架中
  • 在框架中,去查询数据库得到body,此时把body返回给服务器
  • 服务器,把得到的响应头和body,一起返回给浏览器

服务器支持WSGI

第一版,传递给框架的空字典版本

  • 服务器给框架传递的参数时,传递一个空的字典
  • 该版本的框架,只能返回固定的内容

框架支持WSGI

  • 框架中按照WSGI的要求来实现application函数
  • mini_freame.py
def application(environ, start_response):
    start_response('200 OK', [('Content-Type''text/html;charset=utf-8')])
    return 'Hello World! 我爱你中国....'

服务器支持WSGI

  • 服务器端定义一个被框架回调的函数set_response_header(),用于让框架来传递响应头
  • 这里传递给框架的application()中的environ的字典,是一个空字典,也可以传递空字典
  • web_server.py
import socket
import re
import multiprocessing
import time
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 FOUNDrn"
                response += "rn"
                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 OKrn"
                response += "rn"
                # 2.2 准备发送给浏览器的数据---boy
                # response += "hahahhah"

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

            env = dict()
            body = mini_frame.application(env, self.set_response_header)

            header = "HTTP/1.1 %srn" % self.status

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

            header += "rn"

            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()

            # 5. 为这个客户端服务
            p = multiprocessing.Process(target=self.service_client, args=(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()

第二版,传递给框架的字典中存放其他信息

可以在字典中传递请求的路径等信息

框架实现WSGI

  • 从框架中得到的env中提取PATH_INFO,这里面存放的是请求的路径
  • 根据请求的路径,动态的返回内容
def index():
 return "这是主页"

def login():
 return "这是登录页面"

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 == "/login.py":
     return login()
    else:
     return 'Hello World! 我爱你中国....'

服务器支持WSGI

  • 服务器调用框架时传递的env环境变量时,把PATH_INFO传递进去,它代表的是要请求的路径
import socket
import re
import multiprocessing
import time
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 FOUNDrn"
                response += "rn"
                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 OKrn"
                response += "rn"
                # 2.2 准备发送给浏览器的数据---boy
                # response += "hahahhah"

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

            env = dict()
            body = mini_frame.application(env, self.set_response_header)

            header = "HTTP/1.1 %srn" % self.status

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

            header += "rn"

            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()

            # 5. 为这个客户端服务
            p = multiprocessing.Process(target=self.service_client, args=(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框架支持模板功能

  • 当启动服务器后,如果访问的是.py文件的话,就去动态的发送这个请求到web框架
  • web框架根据请求路径,动态找到该请求对应的模板文件
  • 读取模板文件,然后作为响应体返回给服务器
  • 服务器返回给浏览器
  • 该版本的缺点: 这里的模板,是根据请求体返回的数据,是直接读取模板内容然后返回的

web框架mini_freame.py

  • 根据请求,读取对应的文件,返回给服务器
  • 注意:这里的模块文件路径的写法,是以服务器程序运行为起始路径,寻找的,所以下面是一个.,而不是两个..
def index():
    with open("./templates/index.html",encoding="utf-8"as f:
        content = f.read()
    return content

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! 我爱你中国....'

服务器

  • 服务器,如果是.py结尾的文件,就去web框架请求数据
  • 如果是静态文件,直接读取静态文件返回
import socket
import re
import multiprocessing
import time
import dynamic.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("./static" + file_name, "rb")
            except:
                response = "HTTP/1.1 404 NOT FOUNDrn"
                response += "rn"
                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 OKrn"
                response += "rn"
                # 2.2 准备发送给浏览器的数据---boy
                # response += "hahahhah"

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

            env = dict()  # 这个字典中存放的是web服务器要传递给 web框架的数据信息
            env['PATH_INFO'] = file_name
            # {"PATH_INFO": "/index.py"}
            body = dynamic.mini_frame.application(env, self.set_response_header)

            header = "HTTP/1.1 %srn" % self.status

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

            header += "rn"

            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()

            # 5. 为这个客户端服务
            p = multiprocessing.Process(target=self.service_client, args=(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框架增加替换模板中数据功能

在模板文件中增加一些特殊标记的信息

  • 上面的{%content%}就是特殊标记的信息,类似于占位符
  • 当数据返回的时候,是需要被替换成其他内容的

web框架实现替换模板中数据的功能

  • 读取模块中的内容
  • 通过正则得到占位符的信息,然后替换成需要的数据
import re

def index():
    with open("./templates/index.html",encoding="utf-8"as f:
        content = f.read()

    my_stock_info = "哈哈哈哈 这是你的本月名称....."

    content = re.sub(r"{%content%}", my_stock_info, content)

    return content
     

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

    my_stock_info = "这里是从mysql查询出来的数据。。。"

    content = re.sub(r"{%content%}", my_stock_info, content)

    return content
     

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 time
import dynamic.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("./static" + file_name, "rb")
            except:
                response = "HTTP/1.1 404 NOT FOUNDrn"
                response += "rn"
                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 OKrn"
                response += "rn"
                # 2.2 准备发送给浏览器的数据---boy
                # response += "hahahhah"

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

            env = dict()  # 这个字典中存放的是web服务器要传递给 web框架的数据信息
            env['PATH_INFO'] = file_name
            # {"PATH_INFO": "/index.py"}
            body = dynamic.mini_frame.application(env, self.set_response_header)

            header = "HTTP/1.1 %srn" % self.status

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

            header += "rn"

            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()

            # 5. 为这个客户端服务
            p = multiprocessing.Process(target=self.service_client, args=(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框架

  • 该服务器运行的时候,用法如下
  • python3 webservice.py 7890 mini_frame:application
  • 运行服务器webservice.py的时候,指定端口
  • 并且指定了web框架mini_frame,并且运行的是mini_frame框架中的application方法
  • 由于运行时指定了web框架,所以在服务器中不能直接导入这个框架了,而是运行时动态加载框架

服务器

  • 该服务器的缺点:
  • 服务器可以根据传递的web框架调用其运行
  • 但是,该服务器中把web框架的位置写死了,最好通过配置文件来读取
  • webservice.py
import socket
import re
import multiprocessing
import time
# import dynamic.mini_frame
import sys


class WSGIServer(object):
    def __init__(self, port, app):
        # 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

    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("./static" + file_name, "rb")
            except:
                response = "HTTP/1.1 404 NOT FOUNDrn"
                response += "rn"
                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 OKrn"
                response += "rn"
                # 2.2 准备发送给浏览器的数据---boy
                # response += "hahahhah"

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

            env = dict()  # 这个字典中存放的是web服务器要传递给 web框架的数据信息
            env['PATH_INFO'] = file_name
            # {"PATH_INFO": "/index.py"}
            # body = dynamic.mini_frame.application(env, self.set_response_header)
            body = self.application(env, self.set_response_header)

            header = "HTTP/1.1 %srn" % self.status

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

            header += "rn"

            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()

            # 5. 为这个客户端服务
            p = multiprocessing.Process(target=self.service_client, args=(new_socket,))
            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"([^:]+):(.*)", 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


    sys.path.append("./dynamic")

    # 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)
    wsgi_server.run_forever()


if __name__ == "__main__":
    main()

让web服务器支持配置文件

配置文件web_server.conf

  • 配置文件中配置web框架中的位置,和静态文件的文件
{
    "static_path":"./static",
    "dynamic_path":"./dynamic"
}

web框架mini_freame.py

import re


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

    my_stock_info = "哈哈哈哈 这是你的本月名称....."

    content = re.sub(r"{%content%}", my_stock_info, content)

    return content
     

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

    my_stock_info = "这里是从mysql查询出来的数据。。。"

    content = re.sub(r"{%content%}", my_stock_info, content)

    return content
     

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! 我爱你中国....'

服务器web_server.py

  • 这样服务器中,就没有任何写死的web框架的信息了
  • 完全是去配置文件中读取数配置信息,然后直接读取内容找到web框架
import socket
import re
import multiprocessing
import time
# import dynamic.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 FOUNDrn"
                response += "rn"
                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 OKrn"
                response += "rn"
                # 2.2 准备发送给浏览器的数据---boy
                # response += "hahahhah"

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

            env = dict()  # 这个字典中存放的是web服务器要传递给 web框架的数据信息
            env['PATH_INFO'] = file_name
            # {"PATH_INFO": "/index.py"}
            # body = dynamic.mini_frame.application(env, self.set_response_header)
            body = self.application(env, self.set_response_header)

            header = "HTTP/1.1 %srn" % self.status

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

            header += "rn"

            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()

            # 5. 为这个客户端服务
            p = multiprocessing.Process(target=self.service_client, args=(new_socket,))
            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"([^:]+):(.*)", 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()

web框架通过装饰器实现路由

mini_frame.py

  • 该框架中,使用装饰器来修饰函数
  • python文件的执行是从上向下的,遇到装饰器的装饰的函数时,虽然没有调用被装饰的函数,但是其上的装饰器都会执行
  • 所以,定义了一个URL_FUNC_DICT = dict()字典
  • 遇到了装饰器,就把所有被@route装饰的数据方法存放到URL_FUNC_DIC,这里面存放了所有的路由
  • 最后根据请求url,去匹配路由里面的方法,调用返回给服务器
import re

"""
URL_FUNC_DICT = {
    "/index.py": index,
    "/center.py": center
}
"""


URL_FUNC_DICT = dict()


def route(url):
    def set_func(func):
        # URL_FUNC_DICT["/index.py"] = index
        URL_FUNC_DICT[url] = func
        #def call_func(*args, **kwargs):
        #   return func(*args, **kwargs)
        #return call_func
    return set_func


@route("/index.py")   # 相当于 @set_func  # index = set_func(index)  
def index():
    with open("./templates/index.html",encoding="utf-8"as f:
        content = f.read()

    my_stock_info = "哈哈哈哈 这是你的本月名称....."

    content = re.sub(r"{%content%}", my_stock_info, content)

    return content
     

@route("/center.py")
def center():
    with open("./templates/center.html",encoding="utf-8"as f:
        content = f.read()

    my_stock_info = "这里是从mysql查询出来的数据。。。"

    content = re.sub(r"{%content%}", my_stock_info, content)

    return content


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! 我爱你中国....'
    """


    try:
        # func = URL_FUNC_DICT[file_name]
        # return func()
        return URL_FUNC_DICT[file_name]()
    except Exception as ret:
        return "产生了异常:%s" % str(ret)

服务器web_server.py

import socket
import re
import multiprocessing
import time
# import dynamic.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", encoding="utf-8")
            except:
                response = "HTTP/1.1 404 NOT FOUNDrn"
                response += "rn"
                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 OKrn"
                response += "rn"
                # 2.2 准备发送给浏览器的数据---boy
                # response += "hahahhah"

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

            env = dict()  # 这个字典中存放的是web服务器要传递给 web框架的数据信息
            env['PATH_INFO'] = file_name
            # {"PATH_INFO": "/index.py"}
            # body = dynamic.mini_frame.application(env, self.set_response_header)
            body = self.application(env, self.set_response_header)

            header = "HTTP/1.1 %srn" % self.status

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

            header += "rn"

            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()

            # 5. 为这个客户端服务
            p = multiprocessing.Process(target=self.service_client, args=(new_socket,))
            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"([^:]+):(.*)", 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",encoding="utf-8"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()

这里用到的配置文件**web_server.conf**

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


原文始发于微信公众号(Python之家):Python基础-30-动态服务器

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/198443.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!