200行自定义异步非阻塞Web框架-创新互联

老男孩IT教育Python培训教你如何使用python web框架

创新互联公司是一家专注于成都网站建设、网站制作与策划设计,屯溪网站建设哪家好?创新互联公司做网站,专注于网站建设十载,网设计领域的专业建站公司;建站业务涵盖:屯溪等地区。屯溪做网站价格咨询:18980820575

Python的Web框架中Tornado以异步非阻塞而闻名。本篇将使用200行代码完成一个微型异步非阻塞Web框架:Snow。

一、源码

本文基于非阻塞的Socket以及IO多路复用从而实现异步非阻塞的Web框架,其中便是众多异步非阻塞Web框架内部原理。

200行自定义异步非阻塞Web框架

200行自定义异步非阻塞Web框架

#!/usr/bin/env python# -*- coding:utf-8 -*-import reimport socketimport selectimport timeclass HttpResponse(object):   """
   封装响应信息   """
    def __init__(self, content=''):
     self.content = content

     self.headers = {}
     self.cookies = {}   def response(self):     return bytes(self.content, encoding='utf-8')class HttpNotFound(HttpResponse):   """
   404时的错误提示   """
    def __init__(self):
     super(HttpNotFound, self).__init__('404 Not Found')class HttpRequest(object):   """
   用户封装用户请求信息   """
    def __init__(self, conn):
     self.conn = conn

     self.header_bytes = bytes()
     self.header_dict = {}
     self.body_bytes = bytes()

     self.method = ""
     self.url = ""
     self.protocol = ""

     self.initialize()
     self.initialize_headers()   def initialize(self):

     header_flag = False     while True:       try:
         received = self.conn.recv(8096)       except Exception as e:
         received = None       if not received:         break
            if header_flag:
         self.body_bytes += received         continue
       temp = received.split(b'\r\n\r\n', 1)       if len(temp) == 1:
         self.header_bytes += temp       else:
         h, b = temp
         self.header_bytes += h
         self.body_bytes += b
         header_flag = True

   @property   def header_str(self):     return str(self.header_bytes, encoding='utf-8')   def initialize_headers(self):
     headers = self.header_str.split('\r\n')
     first_line = headers[0].split(' ')     if len(first_line) == 3:
       self.method, self.url, self.protocol = headers[0].split(' ')       for line in headers:
         kv = line.split(':')         if len(kv) == 2:
           k, v = kv
           self.header_dict[k] = vclass Future(object):   """
   异步非阻塞模式时封装回调函数以及是否准备就绪   """
    def __init__(self, callback):
     self.callback = callback
     self._ready = False
     self.value = None   def set_result(self, value=None):
     self.value = value
     self._ready = True

   @property   def ready(self):     return self._readyclass TimeoutFuture(Future):   """
   异步非阻塞超时   """
    def __init__(self, timeout):
     super(TimeoutFuture, self).__init__(callback=None)
     self.timeout = timeout
     self.start_time = time.time()

   @property   def ready(self):
     current_time = time.time()     if current_time > self.start_time + self.timeout:
       self._ready = True     return self._readyclass Snow(object):   """
   微型Web框架类   """
    def __init__(self, routes):
     self.routes = routes
     self.inputs = set()
     self.request = None
     self.async_request_handler = {}   def run(self, host='localhost', port=9999):     """
     事件循环
     :param host:
     :param port:
     :return:     """
     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
     sock.bind((host, port,))
     sock.setblocking(False)
     sock.listen(128)
     sock.setblocking(0)
     self.inputs.add(sock)     try:       while True:
         readable_list, writeable_list, error_list = select.select(self.inputs, [], self.inputs,0.005)         for conn in readable_list:           if sock == conn:
             client, address = conn.accept()
             client.setblocking(False)
             self.inputs.add(client)           else:
             gen = self.process(conn)             if isinstance(gen, HttpResponse):
               conn.sendall(gen.response())
               self.inputs.remove(conn)
               conn.close()             else:
               yielded = next(gen)
               self.async_request_handler[conn] = yielded
         self.polling_callback()     except Exception as e:       pass
        finally:
       sock.close()   def polling_callback(self):     """
     遍历触发异步非阻塞的回调函数
     :return:     """
        for conn in list(self.async_request_handler.keys()):
       yielded = self.async_request_handler[conn]       if not yielded.ready:         continue
            if yielded.callback:
         ret = yielded.callback(self.request, yielded)
         conn.sendall(ret.response())
       self.inputs.remove(conn)       del self.async_request_handler[conn]
       conn.close()   def process(self, conn):     """
     处理路由系统以及执行函数
     :param conn:
     :return:     """
     self.request = HttpRequest(conn)
     func = None     for route in self.routes:       if re.match(route[0], self.request.url):
         func = route[1]         break
        if not func:       return HttpNotFound()     else:       return func(self.request)

200行自定义异步非阻塞Web框架

二、使用

1. 基本使用

1

2

3

4

5

6

7

8

9

10

11

12

13

14

from snow import Snow

from snow import HttpResponse

def index(request):

    return HttpResponse('OK')

routes = [

    (r'/index/', index),

]

app = Snow(routes)

app.run(port=8012)

2.异步非阻塞:超时

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

from snow import Snow

from snow import HttpResponse

from snow import TimeoutFuture

request_list = []

def async(request):

    obj = TimeoutFuture(5)

    yield obj

def home(request):

    return HttpResponse('home')

routes = [

    (r'/home/', home),

    (r'/async/', async),

]

app = Snow(routes)

app.run(port=8012)

3.异步非阻塞:等待

基于等待模式可以完成自定制操作

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

from snow import Snow

from snow import HttpResponse

from snow import Future

request_list = []

def callback(request, future):

    return HttpResponse(future.value)

def req(request):

    obj = Future(callback=callback)

    request_list.append(obj)

    yield obj

def stop(request):

    obj = request_list[0]

    del request_list[0]

    obj.set_result('done')

    return HttpResponse('stop')

routes = [

    (r'/req/', req),

    (r'/stop/', stop),

]

app = Snow(routes)

app.run(port=8012)

 更多精彩请关注老男孩教育官网:www.oldboyedu.com

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


分享名称:200行自定义异步非阻塞Web框架-创新互联
标题路径:http://pwwzsj.com/article/dhjjds.html