轉(zhuǎn)帖|使用教程|編輯:黃竹雯|2019-04-15 11:18:30.000|閱讀 568 次
概述:淺談Python中的協(xié)程及利用協(xié)程代替多線程及多進(jìn)程并發(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@ke049m.cn