Python程式中的協程操作 gevent模組

2022-05-07 05:12:06 字數 4885 閱讀 4631

安裝:pip3 install gevent

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

g1=gevent.spawn(func,1,,2,3,x=4,y=5):建立乙個協程物件g1,spawn括號內第乙個引數是函式名,如eat,後面可以有多個引數,可以是位置實參或關鍵字實參,都是傳給函式eat的

g2=gevent.spawn(func2)

g1.join():等待g1結束

g2.join():等待g2結束

上述兩步合作一步:gevent.joinall([g1,g2])

g1.value:拿到func1的返回值

import gevent

def eat(name):

print('%s eat 1' %name)

gevent.sleep(2)

print('%s eat 2' %name)

def play(name):

print('%s play 1' %name)

gevent.sleep(1)

print('%s play 2' %name)

g1=gevent.spawn(eat,'egon')

g2=gevent.spawn(play,name='egon')

g1.join()

g2.join()

# 或者gevent.joinall([g1,g2])

print('主')

上例gevent.sleep(2)模擬的是gevent可以識別的io阻塞,而time.sleep(2)或其他的阻塞,gevent是不能直接識別的需要用下面一行**,打補丁,就可以識別了。

from gevent import monkey;monkey.patch_all()必須放到被打補丁者的前面,如time,socket模組之前。或者我們乾脆記憶成:要用gevent,需要將from gevent import monkey;monkey.patch_all()放到檔案的開頭。

from gevent import monkey;monkey.patch_all()

import gevent

import time

def eat():

print('eat food 1')

time.sleep(2)

print('eat food 2')

def play():

print('play 1')

time.sleep(1)

print('play 2')

g1=gevent.spawn(eat)

g2=gevent.spawn(play)

gevent.joinall([g1,g2])

print('主')

我們可以用threading.current_thread().getname()來檢視每個g1和g2,檢視的結果為dummythread-n,即假執行緒

from gevent import monkey;monkey.patch_all()

import threading

import gevent

import time

def eat():

print(threading.current_thread().getname())

print('eat food 1')

time.sleep(2)

print('eat food 2')

def play():

print(threading.current_thread().getname())

print('play 1')

time.sleep(1)

print('play 2')

g1=gevent.spawn(eat)

g2=gevent.spawn(play)

gevent.joinall([g1,g2])

print('主')

from gevent import spawn,joinall,monkey;monkey.patch_all()

import time

def task(pid):

"""some non-deterministic task

"""time.sleep(0.5)

print('task %s done' % pid)

def synchronous(): # 同步

for i in range(10):

task(i)

def asynchronous(): # 非同步

g_l=[spawn(task,i) for i in range(10)]

joinall(g_l)

print('done')

if __name__ == '__main__':

print('synchronous:')

synchronous()

print('asynchronous:')

asynchronous()

# 上面程式的重要部分是將task函式封裝到greenlet內部執行緒的gevent.spawn。

# 初始化的greenlet列表存放在陣列threads中,此陣列被傳給gevent.joinall 函式,

# 後者阻塞當前流程,並執行所有給定的greenlet任務。執行流程只會在

# 所有greenlet執行完後才會繼續向下走。

通過gevent實現單執行緒下的socket併發

注意:from gevent import monkey;monkey.patch_all()一定要放到匯入socket模組之前,否則gevent無法識別socket的阻塞。

from gevent import monkey;monkey.patch_all()

from socket import *

import gevent

#如果不想用money.patch_all()打補丁,可以用gevent自帶的socket

# from gevent import socket

# s=socket.socket()

def server(server_ip,port):

s=socket(af_inet,sock_stream)

s.setsockopt(sol_socket,so_reuseaddr,1)

s.bind((server_ip,port))

s.listen(5)

while true:

conn,addr=s.accept()

gevent.spawn(talk,conn,addr)

def talk(conn,addr):

try:

while true:

res=conn.recv(1024)

print('client %s:%s msg: %s' %(addr[0],addr[1],res))

conn.send(res.upper())

except exception as e:

print(e)

finally:

conn.close()

if __name__ == '__main__':

server('127.0.0.1',8080)

from socket import *

client=socket(af_inet,sock_stream)

client.connect(('127.0.0.1',8080))

while true:

msg=input('>>: ').strip()

if not msg:continue

client.send(msg.encode('utf-8'))

msg=client.recv(1024)

print(msg.decode('utf-8'))

from threading import thread

from socket import *

import threading

def client(server_ip,port):

c=socket(af_inet,sock_stream)

#套接字物件一定要加到函式內,即區域性命名空間內,放在函式外則被所有執行緒共享,

# 則大家公用乙個套接字物件,那麼客戶端埠永遠一樣了

c.connect((server_ip,port))

count=0

while true:

c.send(('%s say hello %s' %(threading.current_thread().getname(),count)).encode('utf-8'))

msg=c.recv(1024)

print(msg.decode('utf-8'))

count+=1

if __name__ == '__main__':

for i in range(500):

t=thread(target=client,args=('127.0.0.1',8080))

t.start()

Python程式中的協程操作 greenlet模組

目錄安裝 pip3 install greenlet from greenlet import greenlet def eat name print s eat 1 name g2.switch randy print s eat 2 name g2.switch def play name pr...

python協程使用 協程的案例

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

python中協程的優點

1.協程可以讓程式停留在上一次被呼叫的位置.當程式停止時,去執行其他的程式。優點 1 程序和執行緒都面臨著核心態和使用者態的切換問題而耗費許多切換時間,而協程就是使用者自己控制切換的時機,不再需要陷入系統的核心態。協程的執行效率非常高。因為子程式切換不是執行緒切換,而是由程式自身控制。因此,沒有執行...