asyncio

1,事件循環html

import asyncio
import time # time.sleep()是同步阻塞的接口,在async中不可使用
async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)  # 在協程中不要加傳統的等待時間,若是非要加的話,就必須在前面加一個await,代表須要等待它完成
    print("end get url")

if __name__ == "__main__":
    start_time = time.time()
    loop = asyncio.get_event_loop()
    loop.run_until_complete(get_html('www.baidu.com'))
    print(time.time()-start_time)


>>>
start get url
0.0848842123546
end get url

當若是須要多個併發呢?併發

#使用asyncio
import asyncio
import time # time.sleep()是同步阻塞的接口,在async中不可使用
async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)  # 在協程中不要加傳統的等待時間,若是非要加的話,就必須在前面加一個await,代表須要等待它完成
    print("end get url")

if __name__ == "__main__":
    start_time = time.time()
    loop = asyncio.get_event_loop()
    tasks = [get_html("http://www.baidu.com") for i in range(10)]
    loop.run_until_complete(asyncio.wait(tasks))
    print(time.time()-start_time)

最終執行的時間也不過是2sasync

可是若是使用的是time.sleep,就不能夠達成併發ide

1、獲取協程的返回值函數

 

import asyncio
import time
from functools import partial
async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)
    return "OK"

def callback(url, future):
    print(url)
    print("send email to zl")

if __name__ == "__main__":
    start_time = time.time()
    loop = asyncio.get_event_loop()
    # get_future = asyncio.ensure_future(get_html("http://www.imooc.com"))  # 和下面方法等效
    task = loop.create_task(get_html("http://www.imooc.com"))  #和上面方法等效,將協程註冊到事件循環中
    task.add_done_callback(partial(callback, "http://www.imooc.com"))  # 爲何使用偏函數,由於add_done_callback只能接受函數名,所以使用偏函數
    loop.run_until_complete(task)
   print(get_feture.result())
print(task.result())

你可能注意到上面還有一個callback,那這個是幹什麼用的呢?oop

callback:好比在一個URL下載完成以後,給我發送一封郵件,或者是耗時比較長的時候發送郵件url

要注意的是,callback這個函數必需要有參數feture,那若是,我還想繼續傳參呢?spa

就使用partial(偏函數),這個函數能夠將callback進行包裝,可是callback須要額外傳參的時候必須在前面寫!,偏函數的返回值是函數名code

"""
Python 偏函數是經過 functools 模塊被用戶調用。
偏函數 partial 應用

函數在執行時,要帶上全部必要的參數進行調用。可是,有時參數能夠在函數被調用以前提早獲知。這種狀況下,一個函數有一個或多個參數預先就能用上,以便函數能用更少的參數進行調用。

偏函數是將所要承載的函數做爲partial()函數的第一個參數,原函數的各個參數依次做爲partial()函數後續的參數,除非使用關鍵字參數。

經過語言描述可能沒法理解偏函數是怎麼使用的,那麼就舉一個常見的例子來講明。在這個例子裏,咱們實現了一個取餘函數,對於整數 100,取得對於不一樣數 m 的 100%m 的餘數。
"""
from functools import partial
 
def mod( n, m ):
  return n % m
 
mod_by_100 = partial( mod, 100 )
 
print mod( 100, 7 )  # 2
print mod_by_100( 7 )  # 2
View Code

wait和 gatherorm

#wait 和 gather
import asyncio
import time
async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)
    print("end get url")

if __name__ == "__main__":
    start_time = time.time()
    loop = asyncio.get_event_loop()
    tasks = [get_html("http://www.imooc.com") for i in range(10)]
    # loop.run_until_complete(asyncio.gather(*tasks))
    # print(time.time()-start_time)

    #gather和wait的區別(優先考慮gather)
    #gather更加high-level
    group1 = [get_html("http://projectsedu.com") for i in range(2)]
    group2 = [get_html("http://www.imooc.com") for i in range(2)]
    group1 = asyncio.gather(*group1)
    group2 = asyncio.gather(*group2)
    group2.cancel()  # 呈批的取消
    loop.run_until_complete(asyncio.gather(group1, group2))
    print(time.time() - start_time)

協程的暫停:

首先來看一下:

# 1. run_until_complete
import asyncio
loop = asyncio.get_event_loop()
loop.run_forever()  #不會中止
loop.run_until_complete()  # 運行完指定協程後中止
loop會被放到future中
取消future(task)

先看一個例子:

import asyncio
import time

async def get_html(sleep_times):
    print("waiting")
    await asyncio.sleep(sleep_times)
    print("done after {}s".format(sleep_times))


if __name__ == "__main__":
    task1 = get_html(2)
    task2 = get_html(3)
    task3 = get_html(3)

    tasks = [task1, task2, task3]

    loop = asyncio.get_event_loop()
  loop.run_until_complete(asyncio.wait(tasks))
waiting
waiting
waiting
done after 2s
done after 3s
done after 3s

這一個時間循環是沒有問題的

咱們如今須要作的是取消

import asyncio
import time

async def get_html(sleep_times):
    print("waiting")
    await asyncio.sleep(sleep_times)
    print("done after {}s".format(sleep_times))


if __name__ == "__main__":
    task1 = get_html(2)
    task2 = get_html(3)
    task3 = get_html(3)

    tasks = [task1, task2, task3]

    loop = asyncio.get_event_loop()

    try:
        loop.run_until_complete(asyncio.wait(tasks))
    except KeyboardInterrupt as e:
        all_tasks = asyncio.Task.all_tasks()  # 能夠獲取到全部的task
        for task in all_tasks:
            print("cancel task")
            print(task.cancel())
        loop.stop()
        loop.run_forever()  # 這個很關鍵,不調用會拋出異常的 finally:
        loop.close()
相關文章
相關標籤/搜索