成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

PythonAsyncio生產(chǎn)調(diào)度基本原理詳細(xì)信息

89542767 / 523人閱讀

  此篇文章關(guān)鍵闡述了PythonAsyncio生產(chǎn)調(diào)度基本原理詳細(xì)信息,Python.Asyncio是1個專而精的庫,它包括一些功效,而跟關(guān)鍵生產(chǎn)調(diào)度有關(guān)的思路除開三類可在等待目標(biāo)外,還有其他某些功效,他們各自坐落于runners.py,base_event.py,event.py3個文檔中


  序言


  在本文《PythonAsyncio中Coroutines,Tasks,Future可在等待對象關(guān)聯(lián)及功效》中闡述了Python的可在等待目標(biāo)功效,尤其是Task目標(biāo)在運行的時候也可以自我驅(qū)動,但一個Task目標(biāo)只有推動1條實行鏈,如果想好幾條鏈實行(高并發(fā)),也是需要EventLoop來制定推動,下面將采取Python.Asyncio庫的源代碼去了解EventLoop是怎樣運轉(zhuǎn)的。


  1.簡單介紹


  Python.Asyncio是1個專而精的庫,它包括一些功效,而跟關(guān)鍵生產(chǎn)調(diào)度有關(guān)的思路除開三類可在等待目標(biāo)外,還有其他某些功效,他們各自坐落于runners.py,base_event.py,event.py3個文檔中。


  runners.py文件有個最主要的類--Runner,它工作職責(zé)是保證進(jìn)到協(xié)同程序方式的事件循環(huán)直到復(fù)位工作中,及在撤出協(xié)同程序方式時清除仍在運行內(nèi)存的協(xié)同程序,制作器等目標(biāo)。


  協(xié)同程序方式僅僅是為了能便于了解,對電子計算機來說,并沒那樣區(qū)別


  event.py文件除開儲放著EventLoop對象插口及其得到和設(shè)定EventLoop的函數(shù)公式外,兩個EventLoop可生產(chǎn)調(diào)度對象,分別是Handler和TimerHandler,他們能夠稱之為EvnetLoop啟用其他對象器皿,用以連招待生產(chǎn)調(diào)度目標(biāo)和事件循環(huán)之間的關(guān)系,但是它們完成比較簡單,對Handler,它源代碼如下所示:


  #早已移除了個別不愿關(guān)的編碼
  class Handle:
  def __init__(self,callback,args,loop,context=None):
  #初始化上下文,確保執(zhí)行的時候能找到Handle所在的上下文
  if context is None:
  context=contextvars.copy_context()
  self._context=context
  self._loop=loop
  self._callback=callback
  self._args=args
  self._cancelled=False
  def cancel(self):
  #設(shè)置當(dāng)前Handle為取消狀態(tài)
  if not self._cancelled:
  self._cancelled=True
  self._callback=None
  self._args=None
  def cancelled(self):
  return self._cancelled
  def _run(self):
  #用于執(zhí)行真正的函數(shù),且通過context.run方法來確保在自己的上下文內(nèi)執(zhí)行。
  try:
  #保持在自己持有的上下文中執(zhí)行對應(yīng)的回調(diào)
  self._context.run(self._callback,*self._args)
  except(SystemExit,KeyboardInterrupt):
  raise
  except BaseException as exc:
  cb=format_helpers._format_callback_source(
  self._callback,self._args)
  msg=f'Exception in callback{cb}'
  context={
  'message':msg,
  'exception':exc,
  'handle':self,
  }
  self._loop.call_exception_handler(context)


  通過源碼可以發(fā)現(xiàn),Handle功能十分簡單,提供了可以被取消以及可以在自己所處的上下文執(zhí)行的功能,而TimerHandle繼承于Handle比Handle多了一些和時間以及排序相關(guān)的參數(shù),源碼如下:


  class TimerHandle(Handle):
  def __init__(self,when,callback,args,loop,context=None):
  super().__init__(callback,args,loop,context)
  self._when=when
  self._scheduled=False
  def __hash__(self):
  return hash(self._when)
  def __lt__(self,other):
  if isinstance(other,TimerHandle):
  return self._when<other._when
  return NotImplemented
  def __le__(self,other):
  if isinstance(other,TimerHandle):
  return self._when<other._when or self.__eq__(other)
  return NotImplemented
  def __gt__(self,other):
  if isinstance(other,TimerHandle):
  return self._when>other._when
  return NotImplemented
  def __ge__(self,other):
  if isinstance(other,TimerHandle):
  return self._when>other._when or self.__eq__(other)
  return NotImplemented
  def __eq__(self,other):
  if isinstance(other,TimerHandle):
  return(self._when==other._when and
  self._callback==other._callback and
  self._args==other._args and
  self._cancelled==other._cancelled)
  return NotImplemented
  def cancel(self):
  if not self._cancelled:
  #用于通知事件循環(huán)當(dāng)前Handle已經(jīng)退出了
  self._loop._timer_handle_cancelled(self)
  super().cancel()
  def when(self):
  return self._when


  通過代碼可以發(fā)現(xiàn),這兩個對象十分簡單,而我們在使用Python.Asyncio時并不會直接使用到這兩個對象,而是通過loop.call_xxx系列方法來把調(diào)用封裝成Handle對象,然后等待EventLoop執(zhí)行。所以loop.call_xxx系列方法可以認(rèn)為是EventLoop的注冊操作,基本上所有非IO的異步操作都需要通過loop.call_xxx方法來把自己的調(diào)用注冊到EventLoop中,比如Task對象就在初始化后通過調(diào)用loop.call_soon方法來注冊到EventLoop中,loop.call_sonn的實現(xiàn)很簡單,


  它的源碼如下:


  class BaseEventLoop:
  ...
  def call_soon(self,callback,*args,context=None):
  #檢查是否事件循環(huán)是否關(guān)閉,如果是則直接拋出異常
  self._check_closed()
  handle=self._call_soon(callback,args,context)
  return handle
  def _call_soon(self,callback,args,context):
  #把調(diào)用封裝成一個handle,這樣方便被事件循環(huán)調(diào)用
  handle=events.Handle(callback,args,self,context)
  #添加一個handle到_ready,等待被調(diào)用
  self._ready.append(handle)
  return handle


  可以看到call_soon真正相關(guān)的代碼只有10幾行,它負(fù)責(zé)把一個調(diào)用封裝成一個Handle,并添加到self._reday中,從而實現(xiàn)把調(diào)用注冊到事件循環(huán)之中。


  loop.call_xxx系列函數(shù)除了loop.call_soon系列函數(shù)外,還有另外兩個方法--loop.call_at和loop.call_later,它們類似于loop.call_soon,不過多了一個時間參數(shù),來告訴EventLoop在什么時間后才可以調(diào)用,同時通過loop.call_at和loop.call_later注冊的調(diào)用會通過Python的堆排序模塊headpq注冊到self._scheduled變量中,


  具體代碼如下:


  class BaseEventLoop:
  ...
  def call_later(self,delay,callback,*args,context=None):
  if delay is None:
  raise TypeError('delay must not be None')
  timer=self.call_at(self.time()+delay,callback,*args,context=context)
  return timer
  def call_at(self,when,callback,*args,context=None):
  if when is None:
  raise TypeError("when cannot be None")
  self._check_closed()
  #創(chuàng)建一個timer handle,然后添加到事件循環(huán)的_scheduled中,等待被調(diào)用
  timer=events.TimerHandle(when,callback,args,self,context)
  heapq.heappush(self._scheduled,timer)
  timer._scheduled=True
  return timer


  2.EventLoop的調(diào)度實現(xiàn)


  在文章《Python Asyncio中Coroutines,Tasks,Future可等待對象的關(guān)系及作用》中已經(jīng)分析到了runner會通過loop.run_until_complete來調(diào)用mainTask從而開啟EventLoop的調(diào)度,所以在分析EventLoop的調(diào)度時,應(yīng)該先從loop.run_until_complete入手,


  對應(yīng)的源碼如下:


  class BaseEventLoop:
  def run_until_complete(self,future):
  ...
  new_task=not futures.isfuture(future)
  #把coroutine轉(zhuǎn)換成task,這樣事件循環(huán)就可以調(diào)度了,事件循環(huán)的最小調(diào)度單位為task
  #需要注意的是此時事件循環(huán)并沒注冊到全局變量中,所以需要顯示的傳進(jìn)去,
  #同時Task對象注冊的時候,已經(jīng)通過loop.call_soon把自己注冊到事件循環(huán)中,等待調(diào)度
  future=tasks.ensure_future(future,loop=self)
  if new_task:
  #An exception is raised if the future didn't complete,so there
  #is no need to log the"destroy pending task"message
  future._log_destroy_pending=False
  #當(dāng)該task完成時,意味著當(dāng)前事件循環(huán)失去了調(diào)度對象,無法繼續(xù)調(diào)度,所以需要關(guān)閉當(dāng)前事件循環(huán),程序會由協(xié)程模式返回到線程模式
  future.add_done_callback(_run_until_complete_cb)
  try:
  #事件循環(huán)開始運行
  self.run_forever()
  except:
  if new_task and future.done()and not future.cancelled():
  #The coroutine raised a BaseException.Consume the exception
  #to not log a warning,the caller doesn't have access to the
  #local task.
  future.exception()
  raise
  finally:
  future.remove_done_callback(_run_until_complete_cb)
  if not future.done():
  raise RuntimeError('Event loop stopped before Future completed.')
  return future.result()
  def run_forever(self):
  #進(jìn)行一些初始化工作
  self._check_closed()
  self._check_running()
  self._set_coroutine_origin_tracking(self._debug)
  self._thread_id=threading.get_ident()
  old_agen_hooks=sys.get_asyncgen_hooks()
  #通過asyncgen鉤子來自動關(guān)閉asyncgen函數(shù),這樣可以提醒用戶生成器還未關(guān)閉
  sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
  finalizer=self._asyncgen_finalizer_hook)
  try:
  #設(shè)置當(dāng)前在運行的事件循環(huán)到全局變量中,這樣就可以在任一階段獲取到當(dāng)前的事件循環(huán)了
  events._set_running_loop(self)
  while True:
  #正真執(zhí)行任務(wù)的邏輯
  self._run_once()
  if self._stopping:
  break
  finally:
  #關(guān)閉循環(huán),并且清理一些資源
  self._stopping=False
  self._thread_id=None
  events._set_running_loop(None)
  self._set_coroutine_origin_tracking(False)
  sys.set_asyncgen_hooks(*old_agen_hooks)


  這段源碼并不復(fù)雜,它的主要邏輯是通過把Corotinue轉(zhuǎn)為一個Task對象,然后通過Task對象初始化時調(diào)用loop.call_sonn方法把自己注冊到EventLoop中,最后再通過loop.run_forever中的循環(huán)代碼一直運行著,直到_stopping被標(biāo)記為True:


  while True:
  #正真執(zhí)行任務(wù)的邏輯
  self._run_once()
  if self._stopping:
  break
  可以看出,這段代碼是確保事件循環(huán)能一直執(zhí)行著,自動循環(huán)結(jié)束,而真正調(diào)度的核心是_run_once函數(shù),
  它的源碼如下:
  class BaseEventLoop:
  ...
  def _run_once(self):
  #self._scheduled是一個列表,它只存放TimerHandle
  sched_count=len(self._scheduled)
  ###############################
  #第一階段,整理self._scheduled#
  ###############################
  if(sched_count>_MIN_SCHEDULED_TIMER_HANDLES and
  self._timer_cancelled_count/sched_count>_MIN_CANCELLED_TIMER_HANDLES_FRACTION):
  #當(dāng)待調(diào)度的任務(wù)數(shù)量超過100且待取消的任務(wù)占總?cè)蝿?wù)的50%時,才進(jìn)入這個邏輯
  #把需要取消的任務(wù)移除
  new_scheduled=[]
  for handle in self._scheduled:
  if handle._cancelled:
  #設(shè)置handle的_cancelled為True,并且把handle從_scheduled中移除
  handle._scheduled=False
  else:
  new_scheduled.append(handle)
  #重新排列堆
  heapq.heapify(new_scheduled)
  self._scheduled=new_scheduled
  self._timer_cancelled_count=0
  else:
  #需要取消的handle不多,則只會走這個邏輯,這里會把堆頂?shù)膆andle彈出,并標(biāo)記為不可調(diào)度,但不會訪問整個堆
  while self._scheduled and self._scheduled[0]._cancelled:
  self._timer_cancelled_count-=1
  handle=heapq.heappop(self._scheduled)
  handle._scheduled=False
  #################################
  #第二階段,計算超時值以及等待事件IO#
  #################################
  timeout=None
  #當(dāng)有準(zhǔn)備調(diào)度的handle或者是正在關(guān)閉時,不等待,方便盡快的調(diào)度
  if self._ready or self._stopping:
  timeout=0
  elif self._scheduled:
  #Compute the desired timeout.
  #如果堆有數(shù)據(jù)時,通過堆頂?shù)膆andle計算最短的超時時間,但是最多不能超過MAXIMUM_SELECT_TIMEOUT,以免超過系統(tǒng)限制
  when=self._scheduled[0]._when
  timeout=min(max(0,when-self.time()),MAXIMUM_SELECT_TIMEOUT)
  #事件循環(huán)等待事件,直到有事件或者超時
  event_list=self._selector.select(timeout)
  ##################################################
  #第三階段,把滿足條件的TimeHandle放入到self._ready中#
  ##################################################
  #獲取得到的事件的回調(diào),然后裝填到_ready
  self._process_events(event_list)
  #把一些在self._scheduled且滿足調(diào)度條件的handle放到_ready中,比如TimerHandle。
  #end_time為當(dāng)前時間+一個時間單位,猜測是能多處理一些這段時間內(nèi)產(chǎn)生的事件
  end_time=self.time()+self._clock_resolution
  while self._scheduled:
  handle=self._scheduled[0]
  if handle._when>=end_time:
  break
  handle=heapq.heappop(self._scheduled)
  handle._scheduled=False
  self._ready.append(handle)
  ################################################################################
  #第四階段,遍歷所有準(zhǔn)備調(diào)度的handle,并且通過handle的context來執(zhí)行handle對應(yīng)的callback#
  ################################################################################
  ntodo=len(self._ready)
  for i in range(ntodo):
  handle=self._ready.popleft()
  #如果handle已經(jīng)被取消,則不調(diào)用
  if handle._cancelled:
  continue
  if self._debug:
  try:
  self._current_handle=handle
  t0=self.time()
  handle._run()
  dt=self.time()-t0
  if dt>=self.slow_callback_duration:
  #執(zhí)行太久的回調(diào),記錄下來,這些需要開發(fā)者自己優(yōu)化
  logger.warning('Executing%s took%.3f seconds',
  _format_handle(handle),dt)
  finally:
  self._current_handle=None
  else:
  handle._run()
  handle=None#Needed to break cycles when an exception occurs.

  根據(jù)源碼分析,能夠非常明確了解生產(chǎn)調(diào)度邏輯性中首先要先整齊self._scheduled,在整齊的一個過程是采用希爾排序去進(jìn)行的,由于希爾排序在生產(chǎn)調(diào)度的場景中高效率非常高,但是這一段整齊編碼分為二種,我猜測是當(dāng)要關(guān)閉的總數(shù)太多立即賦值效率更高一些。在整齊self._scheduled后,就進(jìn)入了第2步,該流程逐漸等候系統(tǒng)軟件事件循環(huán)回到相對應(yīng)的事情,假如self._ready含有數(shù)據(jù)信息,就不一一等了,必須立刻至下三個步驟,便于能趕快分配生產(chǎn)調(diào)度。在獲得系統(tǒng)軟件事件循環(huán)所得到的事件之后,就進(jìn)入了接著,該流程可以通過self._process_events方法解決相對應(yīng)的事情,然后把事情相對應(yīng)的調(diào)整儲存到self._ready中,接著再賦值self._ready中所有Handle并逐個實行(實行的時候可以覺得EventLoop把管控權(quán)回到給相對應(yīng)的啟用邏輯性),到此一套完整的生產(chǎn)調(diào)度邏輯性就沒有了,并進(jìn)到下個生產(chǎn)調(diào)度邏輯性。


  3.互聯(lián)網(wǎng)IO事件解決


  注:導(dǎo)致系統(tǒng)事件循環(huán)限制,因此材料IO通常依然采用多核來完成,實際見:github.com/python/asyn…


  在研究EventLoop生產(chǎn)調(diào)度完成時忽視了self._process_events的實際完成邏輯性,由于_process_events方法所屬asyncio.base_event.py文件里的BaseEventLoop類并沒有有實際達(dá)到的,由于互聯(lián)網(wǎng)IO有關(guān)的需求全面的事件循環(huán)過來幫忙解決,因此與系統(tǒng)軟件事件循環(huán)有關(guān)的思路都會asyncio.selector_events.py里的BaseSelectorEventLoop類中。BaseSelectorEventLoop類封裝形式了selector模塊與系統(tǒng)軟件事件循環(huán)互動,使調(diào)用者不用去考慮到sock的建立及其sock形成的文件描述符的監(jiān)視與銷戶等行為,下邊以BaseSelectorEventLoop中內(nèi)置的pipe為事例,剖析BaseSelectorEventLoop是如何開始互聯(lián)網(wǎng)IO事故處理的。


  在分析之前,先看一個例子,代碼如下:


  import asyncio
  import threading
  def task():
  print("task")
  def run_loop_inside_thread(loop):
  loop.run_forever()
  loop=asyncio.get_event_loop()
  threading.Thread(target=run_loop_inside_thread,args=(loop,)).start()
  loop.call_soon(task)
  如果直接運行這個例子,它并不會輸出task(不過在IDE使用DEBUG模式下線程啟動會慢一點,所以會輸出的),因為在調(diào)用loop.run_forever后EventLoop會一直卡在這段邏輯中:
  event_list=self._selector.select(timeout)
  所以調(diào)用loop.call_soon并不會使EventLoop馬上安排調(diào)度,而如果把call_soon換成call_soon_threadsafe則可以正常輸出,這是因為call_soon_threadsafe中多了一個self._write_to_self的調(diào)用,它的源碼如下:
  class BaseEventLoop:
  ...
  def call_soon_threadsafe(self,callback,*args,context=None):
  """Like call_soon(),but thread-safe."""
  self._check_closed()
  handle=self._call_soon(callback,args,context)
  self._write_to_self()
  return handle


  由于這個調(diào)用是涉及到IO相關(guān)的,所以需要到BaseSelectorEventLoop類查看,接下來以pipe相關(guān)的網(wǎng)絡(luò)IO操作來分析EventLoop是如何處理IO事件的(只演示reader對象,writer對象操作與reader類似),


  對應(yīng)的源碼如下:


  class BaseSelectorEventLoop(base_events.BaseEventLoop):
  #######
  #創(chuàng)建#
  #######
  def __init__(self,selector=None):
  super().__init__()
  if selector is None:
  #獲取最優(yōu)的selector
  selector=selectors.DefaultSelector()
  self._selector=selector
  #創(chuàng)建pipe
  self._make_self_pipe()
  self._transports=weakref.WeakValueDictionary()
  def _make_self_pipe(self):
  #創(chuàng)建Pipe對應(yīng)的sock
  self._ssock,self._csock=socket.socketpair()
  #設(shè)置sock為非阻塞
  self._ssock.setblocking(False)
  self._csock.setblocking(False)
  self._internal_fds+=1
  #阻塞服務(wù)端sock讀事件對應(yīng)的回調(diào)
  self._add_reader(self._ssock.fileno(),self._read_from_self)
  def _add_reader(self,fd,callback,*args):
  #檢查事件循環(huán)是否關(guān)閉
  self._check_closed()
  #封裝回調(diào)為handle對象
  handle=events.Handle(callback,args,self,None)
  try:
  key=self._selector.get_key(fd)
  except KeyError:
  #如果沒有注冊到系統(tǒng)的事件循環(huán),則注冊
  self._selector.register(fd,selectors.EVENT_READ,
  (handle,None))
  else:
  #如果已經(jīng)注冊過,則更新
  mask,(reader,writer)=key.events,key.data
  self._selector.modify(fd,mask|selectors.EVENT_READ,
  (handle,writer))
  if reader is not None:
  reader.cancel()
  return handle
  def _read_from_self(self):
  #負(fù)責(zé)消費sock數(shù)據(jù)
  while True:
  try:
  data=self._ssock.recv(4096)
  if not data:
  break
  self._process_self_data(data)
  except InterruptedError:
  continue
  except BlockingIOError:
  break
  #######
  #刪除#
  #######
  def _close_self_pipe(self):
  #注銷Pipe對應(yīng)的描述符
  self._remove_reader(self._ssock.fileno())
  #關(guān)閉sock
  self._ssock.close()
  self._ssock=None
  self._csock.close()
  self._csock=None
  self._internal_fds-=1
  def _remove_reader(self,fd):
  #如果事件循環(huán)已經(jīng)關(guān)閉了,就不用操作了
  if self.is_closed():
  return False
  try:
  #查詢文件描述符是否在selector中
  key=self._selector.get_key(fd)
  except KeyError:
  #不存在則返回
  return False
  else:
  #存在則進(jìn)入移除的工作
  mask,(reader,writer)=key.events,key.data
  #通過事件掩碼判斷是否有其它事件
  mask&=~selectors.EVENT_READ
  if not mask:
  #移除已經(jīng)注冊到selector的文件描述符
  self._selector.unregister(fd)
  else:
  #移除已經(jīng)注冊到selector的文件描述符,并注冊新的事件
  self._selector.modify(fd,mask,(None,writer))
  #如果reader不為空,則取消reader
  if reader is not None:
  reader.cancel()
  return True
  else:
  return False
  通過源碼中的創(chuàng)建部分可以看到,EventLoop在啟動的時候會創(chuàng)建一對建立通信的sock,并設(shè)置為非阻塞,然后把對應(yīng)的回調(diào)封裝成一個Handle對象并注冊到系統(tǒng)事件循環(huán)中(刪除則進(jìn)行對應(yīng)的反向操作),之后系統(tǒng)事件循環(huán)就會一直監(jiān)聽對應(yīng)的事件,也就是EventLoop的執(zhí)行邏輯會阻塞在下面的調(diào)用中,等待事件響應(yīng):
  event_list=self._selector.select(timeout)這時如果執(zhí)行l(wèi)oop.call_soon_threadsafe,那么會通過write_to_self寫入一點信息:
  def _write_to_self(self):
  csock=self._csock
  if csock is None:
  return
  try:
  csock.send(b'')
  except OSError:
  if self._debug:
  logger.debug("Fail to write a null byte into the self-pipe socket",exc_info=True)

  由于csock被寫入了數(shù)據(jù),那么它對應(yīng)的ssock就會收到一個讀事件,系統(tǒng)事件循環(huán)在收到這個事件通知后就會把數(shù)據(jù)返回,然后EventLoop就會獲得到對應(yīng)的數(shù)據(jù),并交給process_events方法進(jìn)行處理,


  它的相關(guān)代碼如下:


  class BaseSelectorEventLoop:
  def _process_events(self,event_list):
  for key,mask in event_list:
  #從回調(diào)事件中獲取到對應(yīng)的數(shù)據(jù),key.data在注冊時是一個元祖,所以這里要對元祖進(jìn)行解包
  fileobj,(reader,writer)=key.fileobj,key.data
  if mask&selectors.EVENT_READ and reader is not None:
  #得到reader handle,如果是被標(biāo)記為取消,就移除對應(yīng)的文件描述符
  if reader._cancelled:
  self._remove_reader(fileobj)
  else:
  #如果沒被標(biāo)記為取消,則安排到self._ready中
  self._add_callback(reader)
  if mask&selectors.EVENT_WRITE and writer is not None:
  #對于寫對象,也是同樣的道理。
  if writer._cancelled:
  self._remove_writer(fileobj)
  else:
  self._add_callback(writer)
  def _add_callback(self,handle):
  #把回調(diào)的handle添加到_ready中
  assert isinstance(handle,events.Handle),'A Handle is required here'
  if handle._cancelled:
  return
  assert not isinstance(handle,events.TimerHandle)
  self._ready.append(handle)
  def _remove_reader(self,fd):
  #如果事件循環(huán)已經(jīng)關(guān)閉了,就不用操作了
  if self.is_closed():
  return False
  try:
  #查詢文件描述符是否在selector中
  key=self._selector.get_key(fd)
  except KeyError:
  #不存在則返回
  return False
  else:
  #存在則進(jìn)入移除的工作
  mask,(reader,writer)=key.events,key.data
  mask&=~selectors.EVENT_READ
  if not mask:
  #移除已經(jīng)注冊到selector的文件描述符
  self._selector.unregister(fd)
  else:
  self._selector.modify(fd,mask,(None,writer))
  if reader is not None:
  reader.cancel()
  return True
  else:
  return False


  從編碼中可以看到_process_events會讓事情相對應(yīng)的文件描述符予以處理,并且從事情調(diào)整中掌握到相對應(yīng)的Handle對象添加到self._ready中,由EventLoop在下面賦值self._ready并實施。


  能夠看見互聯(lián)網(wǎng)IO事件解決不復(fù)雜,由于系統(tǒng)軟件事件循環(huán)早已給我們做了許多生活了,可是客戶全部與互聯(lián)網(wǎng)IO有關(guān)實際操作都必須有1個相似的實際操作,那樣是十分繁瑣復(fù)雜,幸好asyncio庫已為我們做了封裝形式,我們只需要啟用就行了,便捷許多。


  綜上所述,這篇文章就給大家介紹到這里了,希望可以為大家?guī)韼椭?/p>

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/129053.html

相關(guān)文章

  • PythonAsyncio中Coroutines,Tasks,Future可等候目標(biāo)關(guān)聯(lián)及功效

      此篇文章關(guān)鍵闡述了PythonAsyncio中Coroutines,Tasks,Future可等候目標(biāo)關(guān)聯(lián)及功效,文章內(nèi)容緊扣主題進(jìn)行詳盡的基本介紹,必須的朋友可以學(xué)習(xí)一下  前記  上一篇閱讀理解《Python中Async語法協(xié)同程序的完成》闡述了Python是如何用制作器來達(dá)到協(xié)同程序的及其PythonAsyncio根據(jù)Future和Task的封裝形式來達(dá)到協(xié)同程序的生產(chǎn)調(diào)度,但在Pyth...

    89542767 評論0 收藏0
  • 從RocketMQ我們學(xué)到了什么之NameServer

    摘要:故事中的下屬們,就是消息生產(chǎn)者角色,屋子右面墻根那塊地就是消息持久化,呂秀才就是消息調(diào)度中心,而你就是消息消費者角色。下屬們匯報的消息,應(yīng)該疊放在哪里,這個消息又應(yīng)該在哪里才能找到,全靠呂秀才的驚人記憶力,才可以讓消息準(zhǔn)確的被投放以及消費。 微信公眾號:IT一刻鐘大型現(xiàn)實非嚴(yán)肅主義現(xiàn)場一刻鐘與你分享優(yōu)質(zhì)技術(shù)架構(gòu)與見聞,做一個有劇情的程序員關(guān)注可了解更多精彩內(nèi)容。問題或建議,請公眾號留言...

    wangbjun 評論0 收藏0
  • 從RocketMQ我們學(xué)到了什么之NameServer

    摘要:故事中的下屬們,就是消息生產(chǎn)者角色,屋子右面墻根那塊地就是消息持久化,呂秀才就是消息調(diào)度中心,而你就是消息消費者角色。下屬們匯報的消息,應(yīng)該疊放在哪里,這個消息又應(yīng)該在哪里才能找到,全靠呂秀才的驚人記憶力,才可以讓消息準(zhǔn)確的被投放以及消費。 微信公眾號:IT一刻鐘大型現(xiàn)實非嚴(yán)肅主義現(xiàn)場一刻鐘與你分享優(yōu)質(zhì)技術(shù)架構(gòu)與見聞,做一個有劇情的程序員關(guān)注可了解更多精彩內(nèi)容。問題或建議,請公眾號留言...

    Arno 評論0 收藏0
  • LVS負(fù)載均衡集群架構(gòu)

    摘要:本文已獲得原作者霸都民工哥授權(quán)。簡單介紹虛擬服務(wù)器,是一個虛擬的服務(wù)器集群系統(tǒng),可以在和系統(tǒng)中運行,年開發(fā)研究的項目。官方網(wǎng)站發(fā)展史在內(nèi)核時,就已經(jīng)以內(nèi)核補丁的形式出現(xiàn)從。 本文已獲得原作者霸都民工哥授權(quán)。 寫在前面 為什么需要使用負(fù)載均衡呢?這是一個必較重要的問題 實際生產(chǎn)環(huán)境中某單臺服務(wù)器已不能負(fù)載日常用訪問壓力時,就需要使用負(fù)載均衡,把用戶的請求數(shù)據(jù)分擔(dān)到(盡可能平均分配)后端所...

    yexiaobai 評論0 收藏0
  • LVS負(fù)載均衡集群架構(gòu)

    摘要:本文已獲得原作者霸都民工哥授權(quán)。簡單介紹虛擬服務(wù)器,是一個虛擬的服務(wù)器集群系統(tǒng),可以在和系統(tǒng)中運行,年開發(fā)研究的項目。官方網(wǎng)站發(fā)展史在內(nèi)核時,就已經(jīng)以內(nèi)核補丁的形式出現(xiàn)從。 本文已獲得原作者霸都民工哥授權(quán)。 寫在前面 為什么需要使用負(fù)載均衡呢?這是一個必較重要的問題 實際生產(chǎn)環(huán)境中某單臺服務(wù)器已不能負(fù)載日常用訪問壓力時,就需要使用負(fù)載均衡,把用戶的請求數(shù)據(jù)分擔(dān)到(盡可能平均分配)后端所...

    Scorpion 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<