python協程重入 Python網路程式設計之協程

2021-10-20 01:13:21 字數 3095 閱讀 4019

what is the association?

與子例程一樣,協程也是一種程式元件。 相對子例程而言,協程更為一般和靈活,但在實踐中使用沒有子例程那樣廣泛。 協程源自simula和modula-2語言,但也有其他語言支援。 協程更適合於用來實現彼此熟悉的程式元件,如合作式多工,迭代器,無限列表和管道。

協程擁有自己的暫存器上下文和棧,協程排程切換時,將暫存器上下文和棧儲存到其他地方,在切回來的時候,恢復先前儲存的暫存器上下文和棧。因此:協程能保留上一次呼叫時的狀態(即所有區域性狀態的乙個特定組合),每次過程重入時,就相當於進入上一次呼叫的狀態,換種說法:進入上一次離開時所處邏輯流的位置。

協程的優缺點:

優點無需執行緒上下文切換的開銷

無需原子操作鎖定及同步的開銷(更改乙個變數)

方便切換控制流,簡化程式設計模型

高併發+高擴充套件性+低成本:乙個cpu支援上萬的協程都不是問題。所以很適合用於高併發處理。

缺點:無法利用多核資源:協程的本質是個單執行緒,它不能多核,協程需要和程序配合才能執行在多cpu上,當然我們日常所編寫的絕大部分應用都沒有這個必要,除非是cpu密集型應用。

進行阻塞(blocking)操作(如io時)會阻塞掉整個程式

實現協程例項

yielddefconsumer(name):

print("--->starting eating baozi...")

whiletrue:

new_baozi=yield# 直接返回

print("[%s] is eating baozi %s"%(name,new_baozi))

defproducer():

r=con.__next__()

r=con2.__next__()

n=0whilen<5:

n+=1

con.send(n)# 喚醒生成器的同時傳入乙個引數

con2.send(n)

print("\033[32;1m[producer]\033[0m is ****** baozi %s"%n)

if__name__=='__main__':

con=consumer("c1")

con2=consumer("c2")

p=producer()

greenlet

安裝greenletpip3 install greenlet# -*- coding:utf-8 -*-

fromgreenletimportgreenlet

deffunc1():

print(12)

gr2.switch()

print(34)

gr2.switch()

deffunc2():

print(56)

gr1.switch()

print(78)

# 建立兩個攜程

gr1=greenlet(func1)

gr2=greenlet(func2)

gr1.switch()# 手動切換

gevent

gevent可以實現併發同步或非同步程式設計,在gevent中用到的主要模式是greenlet, 它是以c擴充套件模組形式接入python的輕量級協程,greenlet全部執行在主程式作業系統程序的內部,但它們被協作式地排程。

安裝geventpip3 install geventimportgevent

deffoo():

print('running in foo')

gevent.sleep(2)

print('explicit context switch to foo again')

defbar():

print('explicit context to bar')

gevent.sleep(3)

print('implicit context switch back to bar')

# 自動切換

gevent.joinall([

gevent.spawn(foo),# 啟動乙個協程

gevent.spawn(bar),

頁面抓取fromurllibimportrequest

fromgeventimportmonkey

importgevent

importtime

monkey.patch_all()# 當前程式中只要設定到io操作的都做上標記

defwget(url):

print('get: %s'%url)

resp=request.urlopen(url)

data=resp.read()

print('%d bytes received from %s.'%(len(data),url))

urls=[

'','',

'','',

# 序列抓取

start_time=time.time()

forninurls:

wget(n)

# 並行抓取

ctrip_time=time.time()

gevent.joinall([

gevent.spawn(wget,''),

gevent.spawn(wget,''),

gevent.spawn(wget,''),

gevent.spawn(wget,''),

輸出c:\python\python35\python.exe e:/mycodeprojects/協程/s4.py

get:

47424bytes receivedfrom.

get:

47424bytes receivedfrom.

get:

25735bytes receivedfrom.

get:

82693bytes receivedfrom.

get:

get:

get:

get:

25736bytes receivedfrom.

47424bytes receivedfrom.

82693bytes receivedfrom.

47424bytes receivedfrom.

processfinishedwithexit code0

python協程與非同步協程

在前面幾個部落格中我們一一對應解決了消費者消費的速度跟不上生產者,浪費我們大量的時間去等待的問題,在這裡,針對業務邏輯比較耗時間的問題,我們還有除了多程序之外更優的解決方式,那就是協程和非同步協程。在引入這個概念之前我們先看 看這個圖 從這個我們可以看出來,假如來了9個任務,即使我們開了多程序,在業...

python協程使用 協程的案例

概念 使用者層面在乙個執行緒中進行多工切換的機制,比執行緒更加輕量級 實現併發量更大 協程的使用 使用第三方庫 gevent gevent 是乙個基於協程的 python 網路庫,在遇到 io 阻塞時,程式會自動進行切換,可以讓我們用同步的放肆寫非同步 io 協程的使用 from gevent im...

python 併發程式設計 協程 協程介紹

協程 是單執行緒下的併發,又稱微執行緒,纖程。英文名coroutine。一句話說明什麼是執行緒 協程是一種使用者態的輕量級執行緒,即協程是由使用者程式自己控制排程的 需要強調的是 1.python的執行緒屬於核心級別的,即由作業系統控制排程 如單執行緒遇到io或執行時間過長就會被迫交出cpu執行許可...