(python)gevent模块(协程用到)

Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程。

用法:

g=gevent.spawn(func,1,……,x=3,……)
#创建一个协程对象g ,spawn括号内第一个参数是函数名,后面可以有多个参数(位置参数,关键字参数)。
g.join()#等待结束
g.value#拿到func的返回值。

遇到IO阻塞时会自动切换任务:

import gevent

def f1():
    print('from f1 1')
    gevent.sleep(3)
    print('from f1 2')

def f2():
    print('from f2 1')
    gevent.sleep(2)
    print('from f2 2')

def f3():
    print('from f3 1')
    gevent.sleep(2)
    print('from f3 2')

g1=gevent.spawn(f1)
g2=gevent.spawn(f2)
g3=gevent.spawn(f3)

# g1.join()
# g2.join()
# g3.join()
gevent.joinall([g1,g2,g3])

上面的例子中gevent.sleep(2)模拟的是gevent可以识别的IO阻塞。

而time.sleep()或其它的阻塞,gevent是不能直接识别的,需要下面一行代码,打补丁识别。

from gevent import monkey;mokey.patch_all()

这一行代码必需放在打补丁者的前面。为了方便,不如直接方在文件的开头位置。

from gevent import monkey,spawn
monkey.patch_all()
import time

def f1():
    print('from f1 1')
    time.sleep(3)
    print('from f1 2')

def f2():
    print('from f2 1')
    time.sleep(2)
    print('from f2 2')

def f3():
    print('from f3 1')
    time.sleep(2)
    print('from f3 2')

g1=spawn(f1)
g2=spawn(f2)
g3=spawn(f3)

g1.join()
g2.join()
g3.join()

接下来我们来通过gevent来实现一个单线程下的socket并发。

服务端:

from gevent import monkey ;monkey.patch_all()
from socket import *
import gevent

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 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(100):
        t=Thread(target=client,args=('127.0.0.1',8080))
        t.start()

运行效果:



猜你喜欢

转载自blog.csdn.net/miaoqinian/article/details/80170824