最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

200行自定義python異步非阻塞Web框架

 更新時(shí)間:2017年03月15日 10:26:37   作者:武沛齊  
本篇將使用200行代碼完成一個(gè)微型異步非阻塞Web框架:Snow。具有很好的參考價(jià)值,下面跟著小編一起來看下吧

Python的Web框架中Tornado以異步非阻塞而聞名。本篇將使用200行代碼完成一個(gè)微型異步非阻塞Web框架:Snow。

一、源碼

本文基于非阻塞的Socket以及IO多路復(fù)用從而實(shí)現(xiàn)異步非阻塞的Web框架,其中便是眾多異步非阻塞Web框架內(nèi)部原理。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
import socket
import select
import time
class HttpResponse(object):
 """
 封裝響應(yīng)信息
 """
 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時(shí)的錯(cuò)誤提示
 """
 def __init__(self):
  super(HttpNotFound, self).__init__('404 Not Found')
class HttpRequest(object):
 """
 用戶封裝用戶請(qǐng)求信息
 """
 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] = v
class Future(object):
 """
 異步非阻塞模式時(shí)封裝回調(diào)函數(shù)以及是否準(zhǔn)備就緒
 """
 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._ready
class TimeoutFuture(Future):
 """
 異步非阻塞超時(shí)
 """
 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._ready
class 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):
  """
  事件循環(huán)
  :param host:
  :param 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:
   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):
  """
  遍歷觸發(fā)異步非阻塞的回調(diào)函數(shù)
  :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):
  """
  處理路由系統(tǒng)以及執(zhí)行函數(shù)
  :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)
snow.py

二、使用

1. 基本使用

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.異步非阻塞:超時(shí)

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.異步非阻塞:等待

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

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)

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持腳本之家!

相關(guān)文章

  • 淺析使用Python操作文件

    淺析使用Python操作文件

    文件操作對(duì)編程語言的重要性不用多說,如果數(shù)據(jù)不能持久保存,信息技術(shù)也就失去了意義。按照本人經(jīng)驗(yàn),IO也是蠻頭疼的一件事,因?yàn)椴粫?huì)用得太多,所以總是記不住API,每次都要重新google就會(huì)打斷思路,還不一定每次都快速得到正確的文章。
    2017-07-07
  • Python如何在單元測(cè)試中給對(duì)象打補(bǔ)丁

    Python如何在單元測(cè)試中給對(duì)象打補(bǔ)丁

    這篇文章主要介紹了Python如何在單元測(cè)試中給對(duì)象打補(bǔ)丁,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-08-08
  • Python LMDB庫的使用示例

    Python LMDB庫的使用示例

    這篇文章主要介紹了Python LMDB庫的使用示例,幫助大家更好的利用python處理數(shù)據(jù)庫,感興趣的朋友可以了解下
    2021-02-02
  • PyCharm實(shí)現(xiàn)遠(yuǎn)程調(diào)試的全過程(附圖文講解)

    PyCharm實(shí)現(xiàn)遠(yuǎn)程調(diào)試的全過程(附圖文講解)

    這篇文章主要介紹了PyCharm實(shí)現(xiàn)遠(yuǎn)程調(diào)試的全過程,文中通過圖文結(jié)合的方式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-05-05
  • python按順序重命名文件并分類轉(zhuǎn)移到各個(gè)文件夾中的實(shí)現(xiàn)代碼

    python按順序重命名文件并分類轉(zhuǎn)移到各個(gè)文件夾中的實(shí)現(xiàn)代碼

    這篇文章主要介紹了python按順序重命名文件并分類轉(zhuǎn)移到各個(gè)文件夾中,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Python實(shí)現(xiàn)批量下載圖片的方法

    Python實(shí)現(xiàn)批量下載圖片的方法

    這篇文章主要介紹了Python實(shí)現(xiàn)批量下載圖片的方法,涉及Python基于urllib、urllib2及re等模塊獲取URL及正則匹配下載圖片的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • python實(shí)現(xiàn)簡(jiǎn)單的單變量線性回歸方法

    python實(shí)現(xiàn)簡(jiǎn)單的單變量線性回歸方法

    今天小編就為大家分享一篇python實(shí)現(xiàn)簡(jiǎn)單的單變量線性回歸方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-11-11
  • Python+django實(shí)現(xiàn)文件上傳

    Python+django實(shí)現(xiàn)文件上傳

    本系列以可操作性為主,介紹如何通過django web框架來實(shí)現(xiàn)一些簡(jiǎn)單的功能。每一篇文章都具有完整性和獨(dú)立性。使用新手在動(dòng)手做的過程中體會(huì)web開發(fā)的過程,過程中細(xì)節(jié)請(qǐng)參考相關(guān)文檔。
    2016-01-01
  • 基于Python和Tkinter實(shí)現(xiàn)高考倒計(jì)時(shí)功能

    基于Python和Tkinter實(shí)現(xiàn)高考倒計(jì)時(shí)功能

    隨著高考的臨近,每個(gè)考生都在緊鑼密鼓地復(fù)習(xí),這時(shí)候,一款實(shí)用的倒計(jì)時(shí)軟件能有效幫助你規(guī)劃剩余時(shí)間,提醒你不要浪費(fèi)每一分每一秒,今天,我們來聊聊一款基于Python和Tkinter開發(fā)的高考倒計(jì)時(shí)軟件,功能簡(jiǎn)單卻極具實(shí)用性,讓你在緊張的備考過程中不再迷失
    2025-03-03
  • Python使用watchfiles實(shí)現(xiàn)監(jiān)控目錄變更

    Python使用watchfiles實(shí)現(xiàn)監(jiān)控目錄變更

    在工作中難免會(huì)碰到這樣的需求,監(jiān)控指定目錄,下面小編就來和大家介紹一下如何利用watchfiles 模塊實(shí)現(xiàn)監(jiān)控目錄的變更,感興趣的可以了解下
    2023-09-09

最新評(píng)論

龙陵县| 闻喜县| 泗水县| 金堂县| 崇明县| 湟中县| 潼南县| 延川县| 云南省| 巴里| 满洲里市| 云阳县| 瑞安市| 张家口市| 珲春市| 松潘县| 金山区| 青河县| 灯塔市| 甘洛县| 韶山市| 新疆| 秦安县| 岑溪市| 色达县| 石门县| 铁力市| 临邑县| 高州市| 长兴县| 永年县| 莱州市| 青岛市| 昌吉市| 富顺县| 黄大仙区| 澎湖县| 丰原市| 新昌县| 大厂| 克拉玛依市|