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