多任務異步操做在爬蟲中的應用

首先來了解幾個概念 :python

  • event_loop:事件循環,至關於一個無限循環,咱們能夠把一些函數註冊到這個事件循環上,當知足某些條件的時候,函數就會被循環執行。程序是按照設定的順序從頭執行到尾,運行的次數也是徹底按照設定。當在編寫異步程序時,必然其中有部分程序的運行耗時是比較久的,須要先讓出當前程序的控制權,讓其在背後運行,讓另外一部分的程序先運行起來。當背後運行的程序完成後,也須要及時通知主程序已經完成任務能夠進行下一步操做,但這個過程所需的時間是不肯定的,須要主程序不斷的監聽狀態,一旦收到了任務完成的消息,就開始進行下一步。loop就是這個持續不斷的監視器。app

  • coroutine:中文翻譯叫協程,在 Python 中常指代爲協程對象類型,咱們能夠將協程對象註冊到事件循環中,它會被事件循環調用。咱們可使用 async 關鍵字來定義一個方法,這個方法在調用時不會當即被執行,而是返回一個協程對象。異步

  • task:任務,它是對協程對象的進一步封裝,包含了任務的各個狀態。async

  • future:表明未來執行或尚未執行的任務,實際上和 task 沒有本質區別。函數

  • 另外咱們還須要瞭解 async/await 關鍵字,它是從 Python 3.5 纔出現的,專門用於定義協程。其中,async 定義一個協程,await 用來掛起阻塞方法的執行. oop

1.獲取一個協程對象 :url

#基本使用
import asyncio
async def hello(name):    #需使用async關鍵字
    print('hello to :',name)
#獲取了一個協程對象
c = hello('xiaohua')

#建立一個事件循環對象
loop = asyncio.get_event_loop()

#將協程對象註冊到事件循環中,而後啓動事件循環對象
loop.run_until_complete(c)  # hello to : xiaohua

2.task的使用spa

import asyncio
async def hello(name):
    print('hello to :',name)

c = hello('xiaohua')
loop = asyncio.get_event_loop()
#就協程進行進一步的封裝,封裝到了task對象中
task = loop.create_task(c)
print(task)
loop.run_until_complete(task)
print(task)

#<Task pending coro=<hello() running at D:/untitled/practice.py:612>>   待執行
#hello to : xiaohua
#<Task finished coro=<hello() done, defined at D:/untitled/practice.py:612> result=None>  執行完畢

 

3.future的使用翻譯

import asyncio

async def hello(name):
    print('hello to :',name)

c = hello('xiaohua')
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(c)

loop.run_until_complete(task)

#hello to : xiaohua

4.回調函數的使用協程

import asyncio
def callback(task): print('i am callback:',task.result()) async def hello(name): print('hello to :',name) return name c = hello('xiaohua') loop = asyncio.get_event_loop() task = asyncio.ensure_future(c) #給任務對象綁定一個回調函數 task.add_done_callback(callback) loop.run_until_complete(task) #hello to : xiaohua #i am callback: xiaohua

5.多任務異步協程示例

import asyncio, time

async def request(url):
    print('正在下載:', url)
    #     sleep(2) #非異步模塊的代碼:在此處若是存在非異步操做代碼,則會完全讓asyncio失去異步的效果
    await asyncio.sleep(2)   #經過await關鍵字實現手動掛起
    print('下載成功:', url)

urls = [
    'www.baidu.com',
    'www.taobao.com',
    'www.sogou.com'
]
start = time.time()
loop = asyncio.get_event_loop()
tasks = []  # 任務列表,放置多個任務對象
for url in urls:
    c = request(url)
    task = asyncio.ensure_future(c)
    tasks.append(task)

# 將多個任務對象對應的列表註冊到事件循環中
loop.run_until_complete(asyncio.wait(tasks))
print('總耗時:', time.time() - start)

結果 : 

  正在下載: www.baidu.com
  正在下載: www.taobao.com
  正在下載: www.sogou.com
  下載成功: www.baidu.com
  下載成功: www.taobao.com
  下載成功: www.sogou.com
  總耗時: 2.0026607513427734

相關文章
相關標籤/搜索