python中的協程:greenlet和gevent
- 協程是一中多任務實現方式,它不需要多個進程或線程就可以實現多任務。
1.通過yield實現協程:
代碼:
import time
def A():
while 1:
print('------A-----')
time.sleep(0.1)
yield()
def B():
while 1:
print('-------B-----')
time.sleep(0.1)
next(a)
a = A()
B()
執行結果:
-------B-----
------A-----
-------B-----
------A-----
-------B-----
------A-----
-------B-----
------A-----
-------B-----
------A-----
···
2.greenlet:
- yield能實現協程,不過實現過程不易於理解,greenlet是在這方面做了改進。
上代碼:
from greenlet import greenlet
import time
def A():
while 1:
print('-------A-------')
time.sleep(0.5)
g2.switch()
def B():
while 1:
print('-------B-------')
time.sleep(0.5)
g1.switch()
g1 = greenlet(A) #創建協程g1
g2 = greenlet(B)
g1.switch() #跳轉至協程g1
執行結果:
-------A-------
-------B-------
-------A-------
-------B-------
-------A-------
···
3.gevent:
- greenlet可以實現協程,不過每一次都要人為的去指向下一個該執行的協程,顯得太過麻煩。python還有一個比greenlet更強大的並且能夠自動切換任務的模塊gevent
- gevent每次遇到io操作,需要耗時等待時,會自動跳到下一個協程繼續執行。
上代碼:
import gevent
def A():
while 1:
print('-------A-------')
gevent.sleep(1) #用來模擬一個耗時操作,注意不是time模塊中的sleep
def B():
while 1:
print('-------B-------')
gevent.sleep(0.5) #每當碰到耗時操作,會自動跳轉至其他協程
g1 = gevent.spawn(A) # 創建一個協程
g2 = gevent.spawn(B)
g1.join() #等待協程執行結束
g2.join()
執行結果:
-------A-------
-------B-------
-------B-------
-------A-------
-------B-------
-------B-------
-------A-------
-------B-------
-------B-------
···
4.協程gevent完成回顯服務器:
import gevent
from gevent import monkey,socket
monkey.patch_all() #有IO才做時需要這一句
s = socket.socket(2,1) #用的都是gevent模塊中的socket,但用法一樣
s.setsockopt(1,2,1)
s.bind(('',8080))
s.listen(1024)
def func_accept():
while 1:
cs,userinfo = s.accept()
print('來了一個客戶'+str(userinfo))
g = gevent.spawn(func_recv,cs) #每當有用戶連接,增加一條協程
def func_recv(cs):
while 1:
recv_data = cs.recv(1024)
print(recv_data) #程誰堵塞了,便會跳轉至其他協程
if len(recv_data) > 0:
cs.send(recv_data)
else:
cs.close()
break
g1 = gevent.spawn(func_accept)
g1.join()
- gevent的代碼風格和線程非常相似,運行出來后的效果也非常相似。