gevent:認識一
import time import gevent # 帶有io操作的內容寫在函數里,然后提交func函數給gevent def func(): print("start func ...") gevent.sleep(1) print("end func ...") g1 = gevent.spawn(func) time.sleep(1.5)
1、程序執行到 g1 = gevent.spawn(func) 這一步之后,並不會執行func協程函數。如果后面沒有了,程序會直接退出。
2、所以需要加個阻塞(io阻塞或其他阻塞),讓程序不能退出,那么程序遇到阻塞就會切換到func協程函數里面執行。那么事實到底是不是呢?
3、這里我是用time.sleep(1.5)阻塞程序的,但是time,sleep(1.5)此時無效,程序等待1.5秒后退出,仍然沒有執行func協程函數。尷尬嘍!因為不認識time為阻塞函數,所以就不會切換到協程函數。那么怎么認識time.sleep()函數呢?就需要導入from gevent import monkey這個啦!
4、協程就是在單線程中,多個任務不停地切換執行。如果線程不阻塞,程序很快運行結束了,那么協程就不會執行的。即使阻塞,也需要讓協程認識才行,這樣才會自動切換到協程函數里面執行。協程認識的阻塞函數就那么幾個,可以查看monkey.patch_all(),主要就是socket的一些阻塞函數。
gevent:認識二
from gevent import monkey monkey.patch_all() import time # 在time之前導入monkey,就認識time阻塞嘍! import gevent # 帶有io操作的內容寫在函數里,然后提交func函數給gevent def func(): print("start func ...") gevent.sleep(1) print("end func ...") g1 = gevent.spawn(func) time.sleep(1.5)
一、gevent 如何檢測是否能規避某個模塊的io操作呢?在patch_all之前打印一次,在patch_all之后打印一次,如果兩次的結果不一樣,那么就說明能夠規避io操作。
二、不容易呀,終於執行協程函數了!但是用time.sleep()函數阻塞不好,因為不清楚協程函數到底需要執行多長時間呢?這里有另一個方法,見下面:
gevent:認識三
from gevent import monkey monkey.patch_all() # 這兩行是為了改變模塊一些特性,如time模塊,socket模塊,這樣才能識別time.sleep()與sock.accept()與sock.recv()等為阻塞函數,進行切換。 import time import gevent def foo(a): print("Running in foo", a) gevent.sleep(2) print("switch to foo again") def func(): print("Running in func ...") gevent.sleep(3) print("switch to func again...") # 將事件函數加入協程,就變成協程函數了 g1 = gevent.spawn(func) g2 = gevent.spawn(foo, 1) # g1.join() # g2.join() gevent.joinall([g1, g2]) # 回收協程,比一個一個回收方便一點
gevent:協程解決網絡阻塞實例,實現並發
服務端:
from gevent import monkey monkey.patch_all() import socket import gevent def func(conn): while True: msg = conn.recv(1024).decode("utf-8") MSG = msg.upper() conn.send(MSG.encode("utf-8")) server = socket.socket() server.bind(("127.0.0.1", 3120)) server.listen() while True: conn, addr = server.accept() gevent.spawn(func, conn)
客戶端:
import time import socket from threading import Thread def client(): client = socket.socket() client.connect(("127.0.0.1", 3120)) while True: client.send(b"hello") data = client.recv(1024) print(data.decode()) time.sleep(1) for i in range(5): Thread(target=client).start()