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
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()