<35>python学习笔记——协程

来源:互联网 发布:霍尔果斯蓝鲸网络 编辑:程序博客网 时间:2024/04/28 06:55

协程是一种用户态的轻量级线程

协程拥有自己的寄存器上下文和栈,能保留上一次调用时的状态。每次过程冲入时,进入上一次离开时所处逻辑流的位置。

协程是串行工作,同一时间只能执行一个携程,不需要加锁。但是进行阻塞(Blocking)操作(如IO操作时)会阻塞掉整个程序。

通过协程在单线程里实现并发效果。

适合做高并发处理。

yield关键字

send()

解决协程阻塞:

greenlet 模块

gevent 模块(基于greenlet模块)

gevent.spawn()启动一个协程

范例:单线程下并发执行一个函数

from urllib.request import urlopenimport geventdef f(url):    print('GET: %s' %url)    resp = urlopen(url)    data = resp.read()    print('%d byte received form %s.'%(len(data),url))#单线程下并发的执行一个下载任务gevent.joinall([    #开启了三个协程    gevent.spawn(f,'https://www.python.org/'),    gevent.spawn(f,'https://www.yahoo.com'),    gevent.spawn(f,'https://github.com/'),])

结果:

GET: https://www.python.org/47410 byte received form https://www.python.org/.GET: https://www.yahoo.com465372 byte received form https://www.yahoo.com.GET: https://github.com/92691 byte received form https://github.com/.

范例:单线程下的多socket并发

server side

import geventfrom gevent import socket,monkeymonkey.patch_all() #monkey 将python中的很多变成非阻塞的形式def server(port):    s = socket.socket()    s.bind(('0.0.0.0',port))    s.listen(500)    while True:        cli,addr = s.accept()        gevent.spawn(handle_request,cli) #启动了一个协程,将cli客户端穿了进来def handle_request(s):    try:        while True:            data = s.recv(1024)            print('recv:',data)            s.send(data)            if not data: #没有数据就断开了                s.shutdown(socket.SHUT_WR) #把客户端销毁    except Exception as ex:        print(ex)    finally:        s.close() #把跟这个客户端的链接关掉if __name__ =='__main__':    server(8001) #启动在8001端口
client side

import socketHOST = 'localhost'PORT = 8001s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.connect((HOST,PORT))while True:    msg = bytes(input('>>:'),encoding='utf8')    s.sendall(msg)    data = s.recv(1024)    print('Reveived',repr(data))s.close()






0 0
原创粉丝点击