首页 > 技术文章 > Web开发---路由实现

xiaoshayu520ly 2019-07-23 15:48 原文

类Flask框架实现

路由route

路由功能实现

路由类实现

#路由
# url = 'http://127.0.0.1:9999/python/index.html?id=5&name=wayne&age=20'
#  path = '/python/index.html'

class Router:
    ROUTETABLE = {}

    def register(self,path,handler):
        self.ROUTETABLE[path] = handler

def indexhandler(request):
    return '<h1>欢迎来到index.html</h1>'

def pythonhandler(request):
    return "<h1>欢迎来到python.html</h1>"

router = Router()
router.register('/',indexhandler)
router.register('/python',pythonhandler)

404处理

注册函数的改造

将注册函数改造成装饰器

class Router:
    ROUTETABLE = {}
    @classmethod    #注册路由,装饰器
    def register(cls,path):
        def wrapper(handler):
            cls.ROUTETABLE[path] = handler
            return handler
        return wrapper

@Router.register('/')    #indexhandler = Router.register('/')(indexhandler)
def indexhandler(request):
    return '<h1>欢迎来到index.html</h1>'

@Router.register('/python')
def pythonhandler(request):
    return "<h1>欢迎来到python.html</h1>"

将路由功能合并到App类中

from webob import Request,Response
from webob.dec import wsgify
from wsgiref.simple_server import make_server
from webob.exc import HTTPNotFound

class Router:
    ROUTETABLE = {}
    @classmethod    #注册路由,装饰器
    def register(cls,path):
        def wrapper(handler):
            cls.ROUTETABLE[path] = handler
            return handler
        return wrapper

@Router.register('/')    #indexhandler = Router.register('/')(indexhandler)
def indexhandler(request):
    return '<h1>欢迎来到index.html</h1>'

@Router.register('/python')
def pythonhandler(request):
    return "<h1>欢迎来到python.html</h1>"

class App:
    _Router = Router
    @wsgify
    def __call__(self, request:Request):
        try:
            return self._Router.ROUTETABLE[request.path](request)
        except:
            raise HTTPNotFound('<h1>你访问的网页被外星人劫持了</h1>')

if __name__ == '__main__':
    ip = '127.0.0.1'
    port = 9999
    server = make_server(ip,port,App())
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        server.shutdown()
        server.server_close()

路由正则匹配

 

from webob import Request,Response
from webob.dec import wsgify
from wsgiref.simple_server import make_server
from webob.exc import HTTPNotFound
import re

class Router:
    ROUTETABLE = []
    @classmethod    #注册路由,装饰器
    def register(cls,pattern):
        def wrapper(handler):
            cls.ROUTETABLE.append((re.compile(pattern),handler))
            return handler
        return wrapper

@Router.register('^/$')    #indexhandler = Router.register('/')(indexhandler)
def indexhandler(request):
    return '<h1>欢迎来到index.html</h1>'

@Router.register('^/python$')
def pythonhandler(request):
    return "<h1>欢迎来到python.html</h1>"

class App:
    _Router = Router
    @wsgify
    def __call__(self, request:Request):
        for pattern,handler in self._Router.ROUTETABLE:
            if pattern.match(request.path): #正则匹配
                return handler(request)
        raise HTTPNotFound('<h1>你访问的网页被外星人劫持了</h1>')

if __name__ == '__main__':
    ip = '127.0.0.1'
    port = 9999
    server = make_server(ip,port,App())
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        server.shutdown()
        server.server_close()

正则表达式分组捕获

 

from webob import Request,Response
from webob.dec import wsgify
from wsgiref.simple_server import make_server
from webob.exc import HTTPNotFound
import re

class Router:
    ROUTETABLE = []
    @classmethod    #注册路由,装饰器
    def register(cls,pattern):
        def wrapper(handler):
            cls.ROUTETABLE.append((re.compile(pattern),handler))
            return handler
        return wrapper

@Router.register(r'^/$')
@Router.register(r'^/(?P<id>\d+)$')
def indexhandler(request):
    return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.get('id'))

@Router.register('^/python$')
def pythonhandler(request):
    return "<h1>欢迎来到python.html</h1>"

class App:
    _Router = Router
    @wsgify
    def __call__(self, request:Request):
        for pattern,handler in self._Router.ROUTETABLE:
            matcher = pattern.match(request.path)       #正则匹配
            if matcher:
                #动态为request增加属性
                request.groups = matcher.groups()       #所有分组组成的元祖,包括命名分组
                request.groupdict = matcher.groupdict()    #命名分组组成的字典
                return handler(request)
        raise HTTPNotFound('<h1>你访问的网页被外星人劫持了</h1>')

if __name__ == '__main__':
    ip = '127.0.0.1'
    port = 9999
    server = make_server(ip,port,App())
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        server.shutdown()
        server.server_close()

Request Method过滤

1、在register装饰器中增加函参数

class Router:
    ROUTETABLE = []
    @classmethod    #注册路由,装饰器
    def register(cls,method,pattern):
        def wrapper(handler):
            cls.ROUTETABLE.append((method.upper(),re.compile(pattern),handler))
            return handler
        return wrapper

@Router.register('GET',r'^/$')
@Router.register('GET',r'^/(?P<id>\d+)$')
def indexhandler(request):
    return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.get('id'))

2、将register分解成不同方法的装饰器

class Router:
    ROUTETABLE = []
    @classmethod    #注册路由,装饰器
    def register(cls,method,pattern):
        def wrapper(handler):
            cls.ROUTETABLE.append((method.upper(),re.compile(pattern),handler))
            return handler
        return wrapper
    
    @classmethod
    def get(cls,pattern):
        return cls.register('GET',pattern)

from webob import Request,Response
from webob.dec import wsgify
from wsgiref.simple_server import make_server
from webob.exc import HTTPNotFound
import re

class Router:
    ROUTETABLE = [] #列表,有序
    @classmethod    #注册路由,装饰器
    def router(cls,method,pattern):
        def wrapper(handler):
            cls.ROUTETABLE.append((method.upper(),re.compile(pattern),handler))
            return handler
        return wrapper

    @classmethod
    def get(cls,pattern):
        return cls.router('GET',pattern)

    @classmethod
    def post(cls,pattern):
        return cls.router('POST',pattern)

    @classmethod
    def head(cls,pattern):
        return cls.router('HEAD',pattern)

@Router.get(r'^/$')
@Router.router('GET',r'^/(?P<id>\d+)$')
def indexhandler(request):
    return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.get('id'))

@Router.get(r'/python/\d+')
@Router.router('GET','^/python$')
def pythonhandler(request):
    return "<h1>欢迎来到python.html</h1>"

class App:
    _Router = Router
    @wsgify
    def __call__(self, request:Request):
        for method,pattern,handler in self._Router.ROUTETABLE:
            if request.method in method or not method:

                matcher = pattern.match(request.path)       #正则匹配
                if matcher:
                    #动态为request增加属性
                    request.groups = matcher.groups()       #所有分组组成的元祖,包括命名分组
                    request.groupdict = matcher.groupdict()    #命名分组组成的字典
                    return handler(request)
        raise HTTPNotFound('<h1>你访问的网页被外星人劫持了</h1>')

if __name__ == '__main__':
    ip = '127.0.0.1'
    port = 9999
    server = make_server(ip,port,App())
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        server.shutdown()
        server.server_close()

改进

from webob import Request,Response
from webob.dec import wsgify
from wsgiref.simple_server import make_server
from webob.exc import HTTPNotFound
import re

class Router:
    ROUTETABLE = [] #列表,有序
    @classmethod    #注册路由,装饰器
    def router(cls,pattern,*methods):
        def wrapper(handler):
            cls.ROUTETABLE.append(
                (tuple(map(lambda x:x.upper(),methods)),
                 re.compile(pattern),
                 handler)
            )
            return handler
        return wrapper

    @classmethod
    def get(cls,pattern):
        return cls.router(pattern,'GET')

    @classmethod
    def post(cls,pattern):
        return cls.router(pattern,'POST')

    @classmethod
    def head(cls,pattern):
        return cls.router(pattern,'HEAD')

@Router.router(r'^/(?P<id>\d+)$')   #支持所有方法
@Router.get(r'^/$')
def indexhandler(request):
    return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.get('id'))

@Router.get(r'/python/\d+')
@Router.router('^/python$','GET')
def pythonhandler(request):
    return "<h1>欢迎来到python.html</h1>"

class App:
    _Router = Router
    @wsgify
    def __call__(self, request:Request):
        for method,pattern,handler in self._Router.ROUTETABLE:
            if request.method in method or not method:

                matcher = pattern.match(request.path)       #正则匹配
                if matcher:
                    #动态为request增加属性
                    request.groups = matcher.groups()       #所有分组组成的元祖,包括命名分组
                    request.groupdict = matcher.groupdict()    #命名分组组成的字典
                    return handler(request)
        raise HTTPNotFound('<h1>你访问的网页被外星人劫持了</h1>')

if __name__ == '__main__':
    ip = '127.0.0.1'
    port = 9999
    server = make_server(ip,port,App())
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        server.shutdown()
        server.server_close()

路由分组***

from webob import Request,Response
from webob.dec import wsgify
from wsgiref.simple_server import make_server
from webob.exc import HTTPNotFound
import re

class Router:
    def __init__(self,prefix:str=''):
        self._prefix = prefix
        self._routertable = []

    # ROUTETABLE = [] #列表,有序
     #注册路由,装饰器
    def router(self,pattern,*methods):
        def wrapper(handler):
            self._routertable.append(
                (tuple(map(lambda x:x.upper(),methods)),
                 re.compile(pattern),
                 handler)
            )
            return handler
        return wrapper

    def get(self,pattern):
        return self.router(pattern,'GET')

    def post(self,pattern):
        return self.router(pattern,'POST')

    def head(self,pattern):
        return self.router(pattern,'HEAD')

    def match(self,request:Request):
        #必须先匹配前缀
        if not request.path.startswith(self._prefix):
            return  None
        #前缀匹配,说明必须由这个Router实例处理
        for method,pattern,handler in self._routertable:
            if request.method in method or not method:
                #前缀已经是以_prefix开头了,利用replace去掉前缀,且只需要替换一次
                matcher = pattern.match(request.path.replace(self._prefix,'',1))
                if matcher:
                    #动态为request增加属性
                    request.groups = matcher.groups()       #所有分组组成的元祖,包括命名分组
                    request.groupdict = matcher.groupdict()    #命名分组组成的字典
                    return handler(request)

class App:
    _Routers = []   #存储所有一级Router对象

    #注册
    @classmethod
    def register(cls,*routers:Router):
        for router in routers:
            cls._Routers.append(router)

    @wsgify
    def __call__(self, request:Request):
        for router in self._Routers:
            response = router.match(request)
            if response:
                return response
        raise HTTPNotFound('<h1>你访问的网页被外星人劫持了</h1>')

#创建Router对象
python = Router('/python')
index =  Router('')

#注册
App.register(index,python)

@index.router(r'^/(?P<id>\d+)$')   #支持所有方法  http://127.0.0.1:9999/2134
@index.get(r'^/$')                  #http://127.0.0.1:9999/
def indexhandler(request):
    return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.get('id'))

@python.router(r'^\d+$')    #支持所有方法  http://127.0.0.1:9999/python1234
@python.get(r'/python$')    #http://127.0.0.1:9999/python/python
def pythonhandler(request):
    return "<h1>欢迎来到python.html</h1>"

if __name__ == '__main__':
    ip = '127.0.0.1'
    port = 9999
    server = make_server(ip,port,App())
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        server.shutdown()
        server.server_close()

 字典访问属性化

class AttriDict:
    def __init__(self,d:dict):
        self.__dict__.update(d if isinstance(d,dict) else {})

    def __setattr__(self, key, value):
        raise NotImplementedError

    def __repr__(self):
        return "<Attrdict {}>".format(self.__dict__)

d = {'a':1,'b':2}
do = AttriDict(d)
print(do.__dict__)
print(do.a)
print(do.b)

 

#1
class AttriDict:
    def __init__(self,d:dict):
        self.__dict__.update(d if isinstance(d,dict) else {})

    def __setattr__(self, key, value):
        raise NotImplementedError   #不允许修改属性

    def __repr__(self):
        return "<Attrdict {}>".format(self.__dict__)

    def __len__(self):
        return len(self.__dict__)

#2
class Router:
    def match(self,request:Request):
        #必须先匹配前缀
        if not request.path.startswith(self._prefix):
            return  None
        #前缀匹配,说明必须由这个Router实例处理
        for method,pattern,handler in self._routertable:
            if request.method in method or not method:
                #前缀已经是以_prefix开头了,利用replace去掉前缀,且只需要替换一次
                matcher = pattern.match(request.path.replace(self._prefix,'',1))
                if matcher:
                    #动态为request增加属性
                    request.groups = matcher.groups()       #所有分组组成的元祖,包括命名分组
                    request.groupdict = AttriDict(matcher.groupdict())    #命名分组组成的字典
                    return handler(request)

#3
@index.router(r'^/(?P<id>\d+)$')   #支持所有方法  http://127.0.0.1:9999/2134
@index.get(r'^/$')                  #http://127.0.0.1:9999/
def indexhandler(request):
    # return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.get('id'))
    return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.id)

正则表达式的化简***

 

 #类型字符串映射到正则表达式
    TYPEPATTERNS = {
        'str':r'[^/]+',
        'word':r'\w+',
        'int':r'[+-]?\d+',
        'float':r'[+-]?\d+\.\d+',
        'any':r'.+'
    }
#类型字符串到python类型的映射
    TYPECAST = {
        'str':str,
        'word':str,
        'int':int,
        'float':float,
        'any':str
    }

import re
#1
pattern = r'\d+'
repl = ''
src = 'welcome 123 to 456'

regex = re.compile(pattern)
dest = regex.sub(repl,src)
print(dest)#welcome  to

#2
pattern = r'/{([^{}:]+):?([^{}:]*)}'
src = '/student/{name}/xxx/{id:int}'
print(src)

def repl(matcher):
    print(matcher.group(0))
    print(matcher.group(1))
    print(matcher.group(2)) #{name}或{name:}这个分组都匹配为''
    return '/(?P<{}>{})'.format(
            matcher.group(1),
            'T' if matcher.group(2) else 'F'
        )

regex = re.compile(pattern)
dest  = regex.sub(repl,src)
print(dest)     #/student/(?P<name>F)/xxx/(?P<id>T)

import re
regex = re.compile(r'/{([^{}:]+):?([^{}:]*)}')
s = [
    '/student/{name:str}/xxx/{id:int}',
    '/student/xxx/{id:int}/yyy',
    '/student/xxx/6454654',
    '/student/{name:}/xxx/{id:aaa}',
    '/student/{name:}/xxx/{id:aaa}'
]

TYPEPATTERNS = {
    'str': r'[^/]+',
    'word': r'\w+',
    'int': r'[+-]?\d+',
    'float': r'[+-]?\d+\.\d+',
    'any': r'.+'
}

def repl(matcher):
    return '/(?P<{}>{})'.format(
        matcher.group(1),
        TYPEPATTERNS.get(matcher.group(2),TYPEPATTERNS['str'])
    )

def parse(src:str):
    return regex.sub(repl,src)

for x in s:
    print(parse(x))
    
#运行结果如下:
# /student/(?P<name>[^/]+)/xxx/(?P<id>[+-]?\d+)
# /student/xxx/(?P<id>[+-]?\d+)/yyy
# /student/xxx/6454654
# /student/(?P<name>[^/]+)/xxx/(?P<id>[^/]+)
# /student/(?P<name>[^/]+)/xxx/(?P<id>[^/]+)

将上面的代码合入Router类中

 

from webob import Request,Response
from webob.exc import HTTPNotFound
from webob.dec import wsgify
from wsgiref.simple_server import make_server
import re

class AttrDict:
    def __init__(self,d:dict):
        self.__dict__.update(d if isinstance(d,dict) else {})

    def __setattr__(self, key, value):
        #不允许修改属性
        raise NotImplementedError

    def __repr__(self):
        return "<AttrDict {}>".format(self.__dict__)

    def __len__(self):
        return len(self.__dict__)

class Router:
    __regex = re.compile(r'/{([^{}:]+):?([^{}:]*)}')

    TYPEPATTERNS = {
        'str':r'[^/]+',
        'word':r'\w+',
        'int':r'[+-]?\d+',
        'float':r'[+-]?\d+\.\d+',
        'any':r'.+'
    }

    def __repl(self,matcher):
        return '/(?P<{}>{})'.format(
            matcher.group(1),
            self.TYPEPATTERNS.get(matcher.group(2),self.TYPEPATTERNS['str'])
        )

    def __parse(self,src:str):
        return self.__regex.sub(self.__repl,src)

    #####实例
    def __init__(self,prefix:str=''):
        self.__prefix = prefix.rstrip('/\\')    #前缀,例如/product
        self.__routetable = []  #存三元组,列表,有序的

    def route(self,pattern,*methods):    #注册路由
        def wrapper(handler):
            #/student/{name:str}/xxx/{id:int}  ==>  '/student/(?P<name>[^/]+/xxx/(?P<id>[+-]\\d+))'
            self.__routetable.append(
                (tuple(map(lambda x:x.upper(),methods)),
                 re.compile(self.__parse(pattern)),
                 handler
                 )
            )
            return handler
        return wrapper

    def get(self,pattern):
        return self.route(pattern,'GET')

    def post(self,pattern):
        return self.route(pattern,'POST')

    def head(self,pattern):
        return self.route(pattern,'HEAD')

    def match(self,request:Request):
        #必须先匹配前缀
        if not request.path.startswith(self.__prefix):
            return None
        #前缀匹配,说明就必须这个Router实例处理,后续匹配不上,依然返回None
        for methods,pattern,handler in self.__routetable:
            # not methods表示一个方法都没有定义,就是支持全部方法
            if not methods or request.method.upper() in methods:
                #前提是以__prefix开头了,可以replace,去掉prefix剩下的才是正则表达式需要匹配的路径
                matcher = pattern.match(request.path.replace(self.__prefix,'',1))
                if matcher:#正则匹配
                    #动态增加属性
                    request.groups = matcher.groups()#所有分组组成的元组,包括命名分组
                    request.groupdict =AttrDict(matcher.groupdict())#命名分组组成的字典被属性化
                    return handler(request)

class App:
    _ROUTERS = []   #存储所有一级对象

    #注册
    @classmethod
    def register(cls,*routers:Router):
        for router in routers:
            cls._ROUTERS.append(router)

    @wsgify
    def __call__(self, request:Request):
        #遍历_ROUTERS,调用Router实例的match方法,进行匹配
        for router in self._ROUTERS:
            response = router.match(request)
            if response:    #匹配返回非None的Router对象
                return response
        raise HTTPNotFound

#创建Router对象
idx = Router()
py = Router('/python')

#注册
App.register(idx,py)

@idx.get(r'^/$')
@idx.route(r'^/{id:int}$')  #支持所有方法
def indexhandler(request):
    id = ''
    if request.groupdict:
        id = request.groupdict.id
    return '<h1>magedu.com{}欢迎你</h1>'.format(id)

@py.get(r'^/{id}$')
def pythonhandler(request):
    res = Response()
    res.charset = 'utf-8'
    res.body = '<h1>welcome to Python</h1>'.encode()
    return res

if __name__ == '__main__':
    ip = '127.0.0.1'
    port= 9999
    server = make_server(ip,port,App)
    try:
        server.serve_forever() # server.handle_request() 一次
    except KeyboardInterrupt:
        server.shutdown()
        server.server_close()

from webob import Request,Response
from webob.exc import HTTPNotFound
from webob.dec import wsgify
from wsgiref.simple_server import make_server
import re

class AttrDict:
    def __init__(self,d:dict):
        self.__dict__.update(d if isinstance(d,dict) else {})

    def __setattr__(self, key, value):
        #不允许修改属性
        raise NotImplementedError

    def __repr__(self):
        return "<AttrDict {}>".format(self.__dict__)

    def __len__(self):
        return len(self.__dict__)

class Router:
    __regex = re.compile(r'/{([^{}:]+):?([^{}:]*)}')

    TYPEPATTERNS = {
        'str':r'[^/]+',
        'word':r'\w+',
        'int':r'[+-]?\d+',
        'float':r'[+-]?\d+\.\d+',
        'any':r'.+'
    }

    TYPECAST = {
        'str':str,
        'word':str,
        'int':int,
        'float':float,
        'any':str
    }

    def __parse(self,src: str):
        start = 0
        repl = ''
        types = {}

        matchers = self.__regex.finditer(src)
        for i, matcher in enumerate(matchers):
            name = matcher.group(1)
            t = matcher.group(2)
            types[name] = self.TYPECAST.get(t, str)

            repl += src[start:matcher.start()]  #拼接分组前
            tmp = '/(?P<{}>{})'.format(
                matcher.group(1),
                self.TYPEPATTERNS.get(matcher.group(2), self.TYPEPATTERNS['str'])
            )
            repl += tmp  # 替换
            start = matcher.end()   #移动
        else:
            repl += src[start:]  # 拼接分组后的内容
        return repl, types

    #####实例
    def __init__(self,prefix:str=''):
        self.__prefix = prefix.rstrip('/\\')    #前缀,例如/product
        self.__routetable = []  #存四元组,列表,有序的

    def route(self,rule,*methods):    #注册路由
        def wrapper(handler):
            #/student/{name:str}/xxx/{id:int}  ==>  '/student/(?P<name>[^/]+/xxx/(?P<id>[+-]\\d+))'
            pattern,trans = self.__parse(rule)  # 用户输入规则转换为正则表达式
            self.__routetable.append(
                (tuple(map(lambda x:x.upper(),methods)),
                 re.compile(pattern),
                 trans,
                 handler
                 )#(方法元组,预编译正则对象,类型转换,处理函数)
            )
            return handler
        return wrapper

    def get(self,pattern):
        return self.route(pattern,'GET')

    def post(self,pattern):
        return self.route(pattern,'POST')

    def head(self,pattern):
        return self.route(pattern,'HEAD')

    def match(self,request:Request):
        #必须先匹配前缀
        if not request.path.startswith(self.__prefix):
            return None
        #前缀匹配,说明就必须这个Router实例处理,后续匹配不上,依然返回None
        for methods,pattern,trans,handler in self.__routetable:
            # not methods表示一个方法都没有定义,就是支持全部方法
            if not methods or request.method.upper() in methods:
                #前提是以__prefix开头了,可以replace,去掉prefix剩下的才是正则表达式需要匹配的路径
                matcher = pattern.match(request.path.replace(self.__prefix,'',1))
                if matcher:#正则匹配
                    newdict = {}
                    for k,v in matcher.groupdict().items():
                        newdict[k] = trans[k](v)
                    #动态增加属性
                    request.groupdict =AttrDict(newdict)#命名分组组成的字典被属性化
                    return handler(request)

class App:
    _ROUTERS = []   #存储所有一级对象

    #注册
    @classmethod
    def register(cls,*routers:Router):
        for router in routers:
            cls._ROUTERS.append(router)

    @wsgify
    def __call__(self, request:Request):
        #遍历_ROUTERS,调用Router实例的match方法,进行匹配
        for router in self._ROUTERS:
            response = router.match(request)
            if response:    #匹配返回非None的Router对象
                return response
        raise HTTPNotFound('<h1>你访问的页面不存在!</h1>')

#创建Router对象
idx = Router()
py = Router('/python')

#注册
App.register(idx,py)

@idx.get(r'^/$')
@idx.route(r'^/{id:int}$')  #支持所有方法
def indexhandler(request):
    id = ''
    if request.groupdict:
        id = request.groupdict.id
    return '<h1>magedu.com{}欢迎你</h1>'.format(id)

@py.get(r'^/{id}$')
def pythonhandler(request):
    if request.groupdict:
        print(type(request.groupdict.id))
    res = Response()
    res.charset = 'utf-8'
    res.body = '<h1>welcome to Python</h1>'.encode()
    return res

if __name__ == '__main__':
    ip = '127.0.0.1'
    port= 9999
    server = make_server(ip,port,App())
    try:
        server.serve_forever() # server.handle_request() 一次
    except KeyboardInterrupt:
        server.shutdown()
        server.server_close()

框架处理流程

 

 

推荐阅读