協程
協程的概念
協程,又稱微線程,纖程,也稱為使用者級線程,在不開辟線程的基礎上完成多任務,也就是在單線程的情況下完成多任務,多個任務按照一定順序交替執行 通俗了解隻要在def裡面隻看到一個yield關鍵字表示就是協程
協程也是實作多任務的一種方式
greentlet的介紹
為了更好使用協程來完成多任務,python中的greenlet子產品對其封裝,進而使得切換任務變的更加簡單
使用如下指令安裝greenlet子產品:
pip3 install greenlet
import time
import greenlet
# 任務1
def work1():
for i in range():
print("work1...")
time.sleep()
# 切換到協程2裡面執行對應的任務
g2.switch()
# 任務2
def work2():
for i in range():
print("work2...")
time.sleep()
# 切換到第一個協程執行對應的任務
g1.switch()
if __name__ == '__main__':
# 建立協程指定對應的任務
g1 = greenlet.greenlet(work1)
g2 = greenlet.greenlet(work2)
# 切換到第一個協程執行對應的任務
g1.switch()
運作效果:
work1...
work2...
work1...
work2...
work1...
work2...
work1...
work2...
work1...
work2...
gevent 介紹
greenlet已經實作了協程,但是這個還要人工切換,這裡介紹一個比greenlet更強大而且能夠自動切換任務的第三方庫,那就是gevent。
gevent内部封裝的greenlet,其原理是當一個greenlet遇到IO(指的是input output 輸入輸出,比如網絡、檔案操作等)操作時,比如通路網絡,就自動切換到其他的greenlet,等到IO操作完成,再在适當的時候切換回來繼續執行。
由于IO操作非常耗時,經常使程式處于等待狀态,有了gevent為我們自動切換協程,就保證總有greenlet在運作,而不是等待IO
import gevent
def work(n):
for i in range(n):
# 擷取目前協程
print(gevent.getcurrent(), i)
#用來模拟一個耗時操作,注意不是time子產品中的sleep
gevent.sleep()
g1 = gevent.spawn(work, )
g2 = gevent.spawn(work, )
g3 = gevent.spawn(work, )
g1.join()
g2.join()
g3.join()
運作結果:
<Greenlet at 0x7fa70ffa1c30: f(5)> 0
<Greenlet at 0x7fa70ffa1870: f(5)> 0
<Greenlet at 0x7fa70ffa1eb0: f(5)> 0
<Greenlet at 0x7fa70ffa1c30: f(5)> 1
<Greenlet at 0x7fa70ffa1870: f(5)> 1
<Greenlet at 0x7fa70ffa1eb0: f(5)> 1
<Greenlet at 0x7fa70ffa1c30: f(5)> 2
<Greenlet at 0x7fa70ffa1870: f(5)> 2
<Greenlet at 0x7fa70ffa1eb0: f(5)> 2
<Greenlet at 0x7fa70ffa1c30: f(5)> 3
<Greenlet at 0x7fa70ffa1870: f(5)> 3
<Greenlet at 0x7fa70ffa1eb0: f(5)> 3
<Greenlet at 0x7fa70ffa1c30: f(5)> 4
<Greenlet at 0x7fa70ffa1870: f(5)> 4
<Greenlet at 0x7fa70ffa1eb0: f(5)> 4
注意:
目前程式是一個死循環并且還能有耗時操作,就不需要加上join方法了,因為程式需要一直運作不會退出
import gevent
import time
from gevent import monkey
# 打更新檔,讓gevent架構識别耗時操作,比如:time.sleep,網絡請求延時
monkey.patch_all()
# 任務1
def work1(num):
for i in range(num):
print("work1....")
time.sleep()
# gevent.sleep(0.2)
# 任務1
def work2(num):
for i in range(num):
print("work2....")
time.sleep()
# gevent.sleep(0.2)
if __name__ == '__main__':
# 建立協程指定對應的任務
g1 = gevent.spawn(work1, )
g2 = gevent.spawn(work2, )
while True:
print("主線程中執行")
time.sleep()
執行結果:
主線程中執行
work1....
work2....
work1....
work2....
work1....
work2....
主線程中執行
主線程中執行
主線程中執行
..省略..
程序 線程 協程對比
程序 線程 協程關系
- 一個程序至少有一個線程,程序裡面可以有多個線程
- 一個線程裡面可以有多個協程
程序 線程 協程對比
- 程序是資源配置設定的機關
- 線程是作業系統排程的機關
- 程序切換需要的資源最大,效率很低
- 線程切換需要的資源一般,效率一般(當然了在不考慮GIL的情況下)
- 協程切換任務資源很小,效率高
- 多程序、多線程根據cpu核數不一樣可能是并行的,但是協程是在一個線程中 是以是并發
總結:
程序、線程、協程都是可以完成多任務的,可以根據自己實際開發的需要選擇使用
由于線程、協程需要的資源很少,是以使用線程和協程的幾率最大
開辟協程需要的資源最少