In Python's web framework, Tornado is known for asynchronous non-blocking. This article will use 200 lines of code to complete a mini asynchronous non-blocking web framework: Snow.
First, the source code
This paper is based on the non-blocking socket and IO multiplexing to implement asynchronous non-blocking web framework, which is the internal principle of many asynchronous non-blocking web frameworks.
#!/usr/bin/env python#-*-coding:utf-8-*-ImportReImportSocketImportSelectImport TimeclassHttpResponse (object):"""Encapsulating Response Information""" def __init__(Self, content="'): Self.content=content Self.headers={} self.cookies= {} defresponse (self):returnBytes (self.content, encoding='Utf-8')classHttpnotfound (httpresponse):"""error message at 404""" def __init__(self): Super (Httpnotfound, self).__init__('404 Not Found')classHttpRequest (object):"""user encapsulates user request information""" 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 ( )defInitialize (self): Header_flag=False whileTrue:Try: Received= Self.conn.recv (8096) exceptException as E:received=Noneif notReceived: Break ifheader_flag:self.body_bytes+=receivedContinueTemp= Received.split (b'\r\n\r\n', 1) ifLen (temp) = = 1: Self.header_bytes+=TempElse: h, b=Temp Self.header_bytes+=h self.body_bytes+=b header_flag=True @propertydefheader_str (self):returnSTR (self.header_bytes, encoding='Utf-8') definitialize_headers (self): headers= Self.header_str.split ('\ r \ n') First_line= Headers[0].split (' ') ifLen (first_line) = = 3: Self.method, Self.url, Self.protocol= Headers[0].split (' ') forLineinchheaders:kv= Line.split (':') ifLen (kv) = = 2: K, v=KV Self.header_dict[k]=vclassFuture (object):"""asynchronous non-blocking mode encapsulates callback functions and is ready""" def __init__(self, callback): Self.callback=Callback Self._ready=False Self.value=NonedefSet_result (Self, value=None): Self.value=value Self._ready=True @propertydefReady (self):returnSelf._readyclasstimeoutfuture (future):"""asynchronous non-blocking timeout""" def __init__(self, timeout): Super (Timeoutfuture, self).__init__(callback=None) Self.timeout=Timeout Self.start_time=time.time () @propertydefReady (self): Current_time=time.time ()ifCurrent_time > Self.start_time +Self.timeout:self._ready=TruereturnSelf._readyclassSnow (object):"""Mini Web Framework class""" def __init__(self, routes): Self.routes=Routes self.inputs=set () Self.request=None Self.async_request_handler= {} defRun (self, host='localhost', port=9999): """event Loop:p Aram Host::p Aram Port:: return:"""sock=Socket.socket (socket.af_inet, socket. Sock_stream) Sock.bind ((host, Port,)) sock.setblocking (False) Sock.listen (128) sock.setblocking (0) self.inputs.add (sock)Try: whiletrue:readable_list, writeable_list, Error_list= Select.select (self.inputs, [], self.inputs,0.005) forConninchreadable_list:ifSock = =conn:client, Address=conn.accept () client.setblocking (False) self.inputs.add (client) Else: Gen=self.process (conn)ifIsinstance (gen, HttpResponse): Conn.sendall (Gen.response ()) SEL F.inputs.remove (conn) conn.close ()Else: Yielded=Next (gen) Self.async_request_handler[conn]=yielded self.polling_callback ()exceptException as E:Pass finally: Sock.close ()defPolling_callback (self):"""traversal triggers an asynchronous non-blocking callback function: return:""" forConninchlist (Self.async_request_handler.keys ()): yielded=Self.async_request_handler[conn]if notYielded.ready:Continue ifYielded.callback:ret=Yielded.callback (Self.request, yielded) Conn.sendall (Ret.response ()) Self.inputs.remove (Con N)delSelf.async_request_handler[conn] Conn.close ()defprocess (SELF, conn):"""handling the routing system and executing functions:P Aram Conn:: Return:"""self.request=HttpRequest (conn) Func=None forRouteinchself.routes:ifRe.match (route[0], Self.request.url): Func= Route[1] Break if notfunc:returnHttpnotfound ()Else: returnFunc (Self.request)
snow.pySecond, use
1. Basic use
From snow import snowfrom Snow Import httpresponsedef Index (Request): return HttpResponse (' OK ') routes = [ (R '/ index/', index),]app = Snow (routes) App.run (port=8012)
2. Asynchronous non-blocking: timeout
From snow import snowfrom Snow import httpresponsefrom Snow Import timeoutfuturerequest_list = []def async (Request): o BJ = timeoutfuture (5) yield Objdef Home (Request): return HttpResponse (' home ') routes = [ (R '/home/', home), (R '/async/', async),]app = Snow (routes) App.run (port=8012)
3. Asynchronous non-blocking: Waiting
Self-customizing operation based on Wait mode
From snow import snowfrom Snow import httpresponsefrom Snow Import futurerequest_list = []def callback (Request, future):
return HttpResponse (Future.value) def req (request): obj = Future (callback=callback) request_list.append ( OBJ) yield objdef 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)
200 rows custom asynchronous non-blocking web framework