Python學習之協程

2022-06-01 21:24:09 字數 3129 閱讀 1741

​ 我們都知道執行緒間的任務切換是由作業系統來控制的,而協程的出現,就是為了減少作業系統的開銷,由協程來自己控制任務的切換

​ 協程本質上就是執行緒。既然能夠切換任務,所以執行緒有兩個最基本的功能:一是儲存狀態;二是任務切換

8.8.1 協程的特點

【優點】

【缺點】

【特點】

8.8.2 greenlet

使用grennlet第三方庫實現任務間的切換

from greenlet import greenlet

def get_money(name):

print(f" get 10 $")

g2.switch('jiawen')

print(f" get 20 $")

g2.switch()

def buy_goods(name):

print(f" buy no.1 good ")

g1.switch()

print(f" buy no.2 good ")

g1.switch()

if __name__ == '__main__':

g1 = greenlet(get_money)

g2 = greenlet(buy_goods)

g1.switch('gailun') # switch在第一次時必須要傳入引數,以後就不需要了

效率對比

from greenlet import greenlet

import time

def f1():

re = 1

for i in range(10000000):

re *= i

g2.switch()

def f2():

re = 1

for i in range(10000000):

re += i

g1.switch()

if __name__ == '__main__':

start = time.time()

g1 = greenlet(f1)

g2 = greenlet(f2)

g1.switch() # switch在第一次時必須要傳入引數,以後就不需要了

print(f'') # 5.822627305984497

import time

def f1():

re = 1

for i in range(10000000):

re *= i

def f2():

re = 1

for i in range(10000000):

re += i

start = time.time()

f1()

f2()

print(f'') # 1.041489601135254

【結論】單純的切換,在沒有io阻塞的情況下,協程的效率反而降低

8.8.3 gevent介紹

gevent也是乙個第三方庫,主要用來實現併發同步或是非同步程式設計,在gevent中用到的主要模式是greenlet, greenlet全部執行在主程式作業系統程序的內部,但它們被協作式地排程。

【方法】

​ gevent.spawn(func,*args,**kwargs) spawn括號內第乙個引數是函式名,後面可以有多個引數,可以是位置實參或關鍵字實參,都是傳給函式func,spawn是非同步提交任務

​ join() 等待呼叫者結束

​ value() 拿到呼叫者的返回值

遇到io阻塞會自動切換

import gevent

def get_money(name):

print(f" get 10 $")

gevent.sleep(2) #模擬的是gevent可以識別的io阻塞

print(f" get 20 $")

def buy_goods(name):

print(f" buy no.1 good ")

gevent.sleep(1)

print(f" buy no.2 good ")

if __name__ == '__main__':

g1 = gevent.spawn(get_money,'gailun')

g2 = gevent.spawn(buy_goods,name='jiawen')

g1.join()

g2.join()

# gevent.joinall([g1,g2])

print('__main__')

# 輸出

gailun get 10 $

jiawen buy no.1 good

jiawen buy no.2 good

gailun get 20 $

__main__

【注意】如果要使gevent識別所有的io阻塞,放到被打補丁者的前面或者直接寫在在檔案的最開頭寫上以下**

rom gevent import monkey;monkey.patch_all()
應用

# 爬蟲

from gevent import monkey;monkey.patch_all()

import gevent

import requests

import time

def get_inf(url):

print(f'get:')

res = requests.get(url)

if res.status_code == 200:

print(f" get from ")

if __name__ == '__main__':

start_time = time.time()

gevent.joinall(

[gevent.spawn(get_inf,''),

gevent.spawn(get_inf,''),

gevent.spawn(get_inf,''),])

print(f"take secondes")

python學習 協程

在學習非同步io模型前,我們先來了解協程。協程,又稱微執行緒,纖程。英文名coroutine。協程的概念很早就提出來了,但直到最近幾年才在某些語言 如lua 中得到廣泛應用。子程式,或者稱為函式,在所有語言中都是層級呼叫,比如a呼叫b,b在執行過程中又呼叫了c,c執行完畢返回,b執行完畢返回,最後是...

Python之協程技術

1.定義 纖程,微執行緒。是允許在不同入口點不同位置暫停或開始的電腦程式,簡單來說,協程就是可以暫停執行的函式。2.協程原理 記錄乙個函式的上下文,協程排程切換時會將記錄的上下文儲存,在切換回來時進行調取,恢復原有的執行內容,以便從上一次執行位置繼續執行。協程本質上就是乙個執行緒,以前多執行緒任務的...

python之協程建立

協程,是充分利用cpu給該執行緒的時間,在乙個執行緒裡放置多個任務,當某個任務阻塞時就執行下乙個任務。其特點是能夠記住這些任務執行到哪一步了,下次再執行該任務的時候回從上次阻塞的地方繼續開始。建立協程需要使用gevent模組。如下 import gevent gevent協程中,遇到需要耗費時間的操...