轉帖|使用教程|編輯:黃竹雯|2019-04-15 11:18:30.000|閱讀 557 次
概述:淺談Python中的協程及利用協程代替多線程及多進程并發編程,與大家分享協程的魅力。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
協程定義說的清楚明了的文章不是很多,手頭上有幾本Python相關的書籍,其中《流暢的Python》一書中解釋協程的定義是小編認為最簡單明了的。
乍看生成器和協程長的可真像,因為都用到了yield關鍵字,那么問題來了,如何區分二者?
def cd(n): print("Counting down from %s" % n) while n > 0: yield n n -= 1 c = cd(10) next(c) for i in c : print(i,end=' ')
上面是一個典型的生成器函數,我們稍加變化使之成為協程。
def cd1(): n = yield while n > 0: print("Counting down from %s" % n) n -= 1 c1 = cd1() next(c1) c1.send(10) #運行到這里應該拋出一個異常
生成器和協程的不同有沒有看出來?很明顯的有兩處:
通過運行結果我們可以到最后拋出了一個異常StopIteration,然后結束了這個協程。我們可以考慮一下:用裝飾器省略掉next()這步,然后捕獲拋出的異常,再關閉掉協程函數。
from functools import wraps def coroutine(func): @wraps(func) def primer(*args, **kwargs): gen = func(*args,**kwargs) next(gen) return gen return primer @coroutine def cd2(): n = yield while n > 0: print("Counting down from %s" % n) n -= 1 try: cd2().send(10) except Exception as e: print('協程任務終止')
帶上了裝飾器,就更簡便一些了,最后捕獲異常,就可以結束這個協程了。
我們想用生成器(協程)作為系統線程的替代方案來實現并發。協程有時也稱為用戶級線程或綠色線程。————引自《Python Cookbook》 這里的協程用到了asyncio模塊,利用asyncio模塊實現了一個協程的并發。關于asyncio的實現原理,之后再研究一下。
import asyncio import time import threading def tn(func): '''定義一個程序運行時間計算函數''' def wrapper(*args, **kwargs): start = time.time() # 起始時間 func(*args, **kwargs) # 要執行的函數 end = time.time() # 結束時間 print('程序運行時間:{:.2f}ms'.format((end-start))) return wrapper def loop1(tname): print(tname+"循環loop1打印時間======" + time.ctime()) time.sleep(1) # @asyncio.coroutine async def loop2(tname):# async等同于@asyncio.coroutine print(tname+"循環loop1打印時間======" + time.ctime()) # yield from asyncio.sleep(1) await asyncio.sleep(1) # 等同于yield from @asyncio.coroutine def loop3(tname):# async等同于@asyncio.coroutine print(tname+"循環loop1打印時間======" + time.ctime()) yield from asyncio.sleep(1) # await asyncio.sleep(1) # 等同于yield from @tn def main(): print('多線程任務開始執行=====') threads = []#定義一個線程隊列 for i in range(5): t = threading.Thread(target=loop1, args=("thread"+str(i),)) threads.append(t) for i in range(5): threads[i].start() for i in range(5): threads[i].join() #協程并發測試 print('協程并發測試開始======') loop = asyncio.get_event_loop()# 獲取一個event_loop #任務列表 tasks = [ asyncio.ensure_future(loop2('11111')), asyncio.ensure_future(loop2('22222')), asyncio.ensure_future(loop2('33333')), asyncio.ensure_future(loop3('44444')),#loop3 asyncio.ensure_future(loop3('55555'))]#loop3 loop.run_until_complete(asyncio.wait(tasks)) loop.close() if __name__ == '__main__': main()
上邊這組代碼稍稍有點亂,可能你需要認真的理下思緒,對比一下結果,你會發現雖然后邊執行的代碼沒有利用多線程,但打印結果上的時間和多線程的執行結果是一樣的。 這就是協程的魅力所在,一條線程搞定多線程任務。
【專業Python IDE推薦】——PyCharm (正版低至¥1068):
PyCharm 是一款Python IDE,其帶有一整套可以幫助用戶在使用Python語言開發時提高其效率的工具。此外,該IDE提供了一些高級功能,以用于Django框架下的專業Web開發。
PyCharm基礎教程推薦:
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn