99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋果6袋
6
麥子學(xué)院

Python 中的異步編程:Asyncio

發(fā)布時(shí)間:2017-05-08 23:47  回復(fù):0  查看:2969   最后回復(fù):2017-05-08 23:47  
本文和大家分享的主要是python 中的 異步編程Asyncio相關(guān)內(nèi)容,一起來看看吧,希望對大家 學(xué)習(xí)python有所幫助。
   異步是怎么一回事?
  在傳統(tǒng)的順序編程中,  所有發(fā)送給解釋器的指令會一條條被執(zhí)行。此類代碼的輸出容易顯現(xiàn)和預(yù)測。  但是
  譬如說你有一個(gè)腳本向3 個(gè)不同服務(wù)器請求數(shù)據(jù)。 有時(shí),誰知什么原因,發(fā)送給其中一個(gè)服務(wù)器的請求可能意外地執(zhí)行了很長時(shí)間。想象一下從第二個(gè)服務(wù)器獲取數(shù)據(jù)用了 10 秒鐘。在你等待的時(shí)候,整個(gè)腳本實(shí)際上什么也沒干。如果你可以寫一個(gè)腳本可以不去等待第二個(gè)請求而是僅僅跳過它,然后開始執(zhí)行第三個(gè)請求,然后回到第二個(gè)請求,執(zhí)行之前離開的位置會怎么樣呢。就是這樣。你通過切換任務(wù)最小化了空轉(zhuǎn)時(shí)間。盡管如此,當(dāng)你需要一個(gè)幾乎沒有 I/O 的簡單腳本時(shí),你不想用異步代碼。
  還有一件重要的事情要提,所有代碼在一個(gè)線程中運(yùn)行。所以如果你想讓程序的一部分在后臺執(zhí)行同時(shí)干一些其他事情,那是不可能的。
   準(zhǔn)備開始
  這是 asyncio  主概念最基本的定義 :
  · 協(xié)程 —  消費(fèi)數(shù)據(jù)的生成器,但是不生成數(shù)據(jù)。 Python 2.5  介紹了一種新的語法讓發(fā)送數(shù)據(jù)到生成器成為可能。
  · 任務(wù) —  協(xié)程調(diào)度器。如果你觀察下面的代碼,你會發(fā)現(xiàn)它只是讓  event_loop  盡快調(diào)用它的 _step  ,同時(shí) _step  只是調(diào)用協(xié)程的下一步。
  class Task(futures.Future):
  def __init__(self, coro, loop=None):
  super().__init__(loop=loop)
  ...
  self._loop.call_soon(self._step)
  def _step(self):
  ...
  try:
  ...
  result = next(self._coro)
  except StopIteration as exc:
  self.set_result(exc.value)
  except BaseException as exc:
  self.set_exception(exc)
  raise
  else:
  ...
  self._loop.call_soon(self._step)
  · 事件循環(huán) —  把它想成  asyncio  的中心執(zhí)行器。
  現(xiàn)在我們看一下所有這些如何融為一體。正如我之前提到的,異步代碼在一個(gè)線程中運(yùn)行。
Python 中的異步編程:Asyncio
     從上圖可知:
 ?。保⒀h(huán)是在線程中執(zhí)行
  2.從隊(duì)列中取得任務(wù)
 ?。常總€(gè)任務(wù)在協(xié)程中執(zhí)行下一步動作
 ?。矗绻谝粋€(gè)協(xié)程中調(diào)用另一個(gè)協(xié)程(await ),會觸發(fā)上下文切換,掛起當(dāng)前協(xié)程,并保存現(xiàn)場環(huán)境(變量,狀態(tài)),然后載入被調(diào)用協(xié)程
 ?。担绻麉f(xié)程的執(zhí)行到阻塞部分(阻塞I/O , Sleep ),當(dāng)前協(xié)程會掛起,并將控制權(quán)返回到線程的消息循環(huán)中,然后消息循環(huán)繼續(xù)從隊(duì)列中執(zhí)行下一個(gè)任務(wù)...以此類推
  6. 隊(duì)列中的所有任務(wù)執(zhí)行完畢后,消息循環(huán)返回第一個(gè)任務(wù)
   異步和同步的代碼對比
  現(xiàn)在我們實(shí)際驗(yàn)證異步模式的切實(shí)有效,我會比較兩段 python  腳本,這兩個(gè)腳本除了  sleep  方法外,其余部分完全相同。在第一個(gè)腳本里,我會用標(biāo)準(zhǔn)的  time.sleep  方法,在第二個(gè)腳本里使用  asyncio.sleep  的異步方法。
  這里使用 Sleep  是因?yàn)樗且粋€(gè)用來展示異步方法如何操作  I/O  的最簡單辦法。
  使用同步 sleep  方法的代碼:
  import asyncio  import time  from datetime import datetime
  async def custom_sleep():
  print('SLEEP', datetime.now())
  time.sleep(1)
  async def factorial(name, number):
  f = 1
  for i in range(2, number+1):
  print('Task {}: Compute factorial({})'.format(name, i))
  await custom_sleep()
  f *= i
  print('Task {}: factorial({}) is {}\n'.format(name, number, f))
  start = time.time()
  loop = asyncio.get_event_loop()
  tasks = [
  asyncio.ensure_future(factorial("A", 3)),
  asyncio.ensure_future(factorial("B", 4)),
  ]
  loop.run_until_complete(asyncio.wait(tasks))
  loop.close()
  end = time.time()
  print("Total time: {}".format(end - start))
  腳本輸出:
  Task A: Compute factorial(2)  SLEEP 2017-04-06 13:39:56.207479  Task A: Compute factorial(3)  SLEEP 2017-04-06 13:39:57.210128  Task A: factorial(3) is 6
  Task B: Compute factorial(2)  SLEEP 2017-04-06 13:39:58.210778  Task B: Compute factorial(3)  SLEEP 2017-04-06 13:39:59.212510  Task B: Compute factorial(4)  SLEEP 2017-04-06 13:40:00.217308  Task B: factorial(4) is 24
  Total time: 5.016386032104492
  使用異步 Sleep   的代碼:
  import asyncio  import time  from datetime import datetime
  async def custom_sleep():
  print('SLEEP {}\n'.format(datetime.now()))
  await asyncio.sleep(1)
  async def factorial(name, number):
  f = 1
  for i in range(2, number+1):
  print('Task {}: Compute factorial({})'.format(name, i))
  await custom_sleep()
  f *= i
  print('Task {}: factorial({}) is {}\n'.format(name, number, f))
  start = time.time()
  loop = asyncio.get_event_loop()
  tasks = [
  asyncio.ensure_future(factorial("A", 3)),
  asyncio.ensure_future(factorial("B", 4)),
  ]
  loop.run_until_complete(asyncio.wait(tasks))
  loop.close()
  end = time.time()
  print("Total time: {}".format(end - start))
  腳本輸出:
  Task A: Compute factorial(2)  SLEEP 2017-04-06 13:44:40.648665
  Task B: Compute factorial(2)  SLEEP 2017-04-06 13:44:40.648859
  Task A: Compute factorial(3)  SLEEP 2017-04-06 13:44:41.649564
  Task B: Compute factorial(3)  SLEEP 2017-04-06 13:44:41.649943
  Task A: factorial(3) is 6
  Task B: Compute factorial(4)  SLEEP 2017-04-06 13:44:42.651755
  Task B: factorial(4) is 24
  Total time: 3.008226156234741
  從輸出可以看到,異步模式的代碼執(zhí)行速度快了大概兩秒。當(dāng)使用異步模式的時(shí)候(每次調(diào)用  await asyncio.sleep(1)  ),進(jìn)程控制權(quán)會返回到主程序的消息循環(huán)里,并開始運(yùn)行隊(duì)列的其他任務(wù)(任務(wù)A或者任務(wù)B)。
  當(dāng)使用標(biāo)準(zhǔn)的 sleep 方法時(shí),當(dāng)前線程會掛起等待。什么也不會做。實(shí)際上,標(biāo)準(zhǔn)的  sleep  過程中,當(dāng)前線程也會返回一個(gè)  python 的解釋器,可以操作現(xiàn)有的其他線程,但這是另一個(gè)話題了。
   推薦使用異步模式編程的幾個(gè)理由
  很多公司的產(chǎn)品都廣泛的使用了異步模式,如 Facebook  旗下著名的  React Native  和  RocksDB  。像  Twitter 每天可以承載  50  億的用戶訪問,靠的也是異步模式編程。所以說 , 通過代碼重構(gòu),或者改變模式方法,就能讓系統(tǒng)工作的更快,為什么不去試一下呢?

來源: 開源中國

您還未登錄,請先登錄

熱門帖子

最新帖子

?