協程greenlet、gevent


greenlet
為了更好使用協程來完成多任務,python中greenlet模塊對其封裝,從而使得切換任務變得更加簡單
安裝方式

pip3 install greenlet

示例代碼:

from greenlet import greenlet
import time

def test1():
while True:
print("-----真-----")
gr2.switch()
time.sleep(0.5)

def test2():
while True:
print("-----真-----")
gr1.switch()
time.sleep(0.5)

gr1 = greenlet(test1)
gr2 = greenlet(test2)

# 切換到gr1中運行
gr1.swith() 


gevent
greenlet已經實現了協程,但是這個工人切換,是不是覺得太麻煩了,不要着急,python還有一個比greenlet更強大的並且能夠自動切換任務的模塊`gevent`
其原理是當一個greentlet遇到IO(指的是input ouput輸入輸出,比如網絡、文件操作等)操作時,比如訪問網絡,就自動切換到其他的greenlet,等到IO完成,再適當的時候切換回來繼續執行。

由於IO操作非常耗時,經常使程序處於等待狀態,有了gevent我們自動切換協程,就保證總有greenlet在運行,而不是等待IO

安裝

pip3 install gevent 

1.gevent的使用

import gevent

def f(n):
for i in range(n):
  print(gevent.getcurrent(), i)
g1
= gevent.spawn(f, 5) g2 = gevent.spawn(f, 5) g3 = gevent.spawn(f, 5) g1.join() g2.join() g3.join()

運行結果 

F:\python3.6\python.exe D:/pythonProjects/pynetwork/coroutine/gevent_demo.py
<Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 0
<Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 1
<Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 2
<Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 3
<Greenlet "Greenlet-0" at 0x22ef10f5c48: f(5)> 4
<Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 0
<Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 1
<Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 2
<Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 3
<Greenlet "Greenlet-1" at 0x22ef12dc048: f(5)> 4
<Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 0
<Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 1
<Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 2
<Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 3
<Greenlet "Greenlet-2" at 0x22ef12dc148: f(5)> 4

Process finished with exit code 0

 

gevent切換執行

import gevent

def f(n):
for i in range(n):
  print(gevent.getcurrent(), i)
  # 用來模擬一個耗時操作,注意不是time模塊中的sleep
  gevent.sleep(1)
g1
= gevent.spawn(f, 5) g2 = gevent.spawn(f, 5) g3 = gevent.spawn(f, 5) g1.join() g2.join() g3.join()

運行結果 

F:\python3.6\python.exe D:/pythonProjects/pynetwork/coroutine/gevent_demo.py
<Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 0
<Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 0
<Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 0
<Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 1
<Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 1
<Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 1
<Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 2
<Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 2
<Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 2
<Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 3
<Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 3
<Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 3
<Greenlet "Greenlet-0" at 0x2c45e304c48: f(5)> 4
<Greenlet "Greenlet-1" at 0x2c45e4cc048: f(5)> 4
<Greenlet "Greenlet-2" at 0x2c45e4cc148: f(5)> 4

Process finished with exit code 0

 

3. 給程序打補丁

from gevent import monkey
import gevent
import random
import time

# 有耗時操作時需要
monkey.patch_all() # 將程序中用到的耗時操作的代碼,換為gevent中自己實現的模塊

def coroutine_work(coroutine_name):
for i in range(10):
print(coroutine_name, i)
time.sleep(random.random())

gevent.joinall([
gevent.spawn(coroutine_work, "work1"),
gevent.spawn(coroutine_work, "work2")
])

運行結果

F:\python3.6\python.exe D:/pythonProjects/pynetwork/coroutine/gevent_test.py
work1 0
work2 0
work2 1
work1 1
work1 2
work1 3
work2 2
work1 4
work1 5
work2 3
work1 6
work1 7
work2 4
work2 5
work1 8
work1 9
work2 6
work2 7
work2 8
work2 9

Process finished with exit code 0

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM