Python学习笔记18(协程)
协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程。
协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:
协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。
那么,什么才能算是协程呢?
- 必须在只有一个单线程里实现并发
- 修改共享数据不需加锁
- 用户程序里自己保存多个控制流的上下文栈
- 一个协程遇到IO操作自动切换到其它协程
一、Greenlet
from greenlet import greenlet def test1(): print(12) gr2.switch() print(34) gr2.switch() def test2(): print(56) gr1.switch() print(78) gr1 = greenlet(test1) gr2 = greenlet(test2) gr1.switch()
greenlet是一个用C实现的协程模块,可以使得你在任意函数之间随意切换。但是,这还不能算做是协程,毕竟切换还是我们自己手动切换的,没有遇到I/O自动切换。
二、Gevent
import gevent def foo(): print("Running in foo,foo开始>>>1") gevent.sleep(2) print('Explicit context switch to foo again foo完成>>>6') def bar(): print('Explicit精确的 context 内容 to bar bar开始>>>2') gevent.sleep(1) print("Imlicit context sitch back to bar bar结束>>>5") def func3(): print('running func3 func3开始>>>3') gevent.sleep(0) print('running func3 again func3结束>>>4') gevent.joinall([ gevent.spawn(foo), gevent.spawn(bar), gevent.spawn(func3), ])
Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。
通过Gevent实现单线程下的多socket并发
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import sys import socket import time import gevent from gevent import socket, monkey #打补丁(把下面有可能有IO操作的单独做上标记) monkey.patch_all() #打补丁 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) def handle_request(conn): try: while True: data = conn.recv(1024) print("recv:", data) conn.send(data) if not data: conn.shutdown(socket.SHUT_WR) except Exception as ex: print(ex) finally: conn.close() if __name__ == '__main__': server(9999)