协程技术

基础概念

1.定义:纤程,微线程。是为非抢占式多任务产生子程序的计算机组件。协程容许不一样入口点在不一样位置暂停或开始,简单来讲,协程就是能够暂停执行的函数。python

2.协程原理 : 记录一个函数的上下文栈帧,协程调度切换时会将记录的上下文保存,在切换回来时进行调取,恢复原有的执行内容,以便从上一次执行位置继续执行。并发

3.协程优缺点异步

优势:socket

  1. 协程完成多任务占用计算资源不多
  2. 因为协程的多任务切换在应用层完成,所以切换开销少
  3. 协程为单线程程序,无需进行共享资源同步互斥处理

缺点:协程的本质是一个单线程,没法利用计算机多核资源async

标准库协程的实现

python3.5之后,使用标准库asyncio和async/await 语法来编写并发代码。asyncio库经过对异步IO行为的支持完成python的协程。虽然官方说asyncio是将来的开发方向,可是因为其生态不够丰富,大量的客户端不支持awaitable须要本身去封装,因此在使用上存在缺陷。更多时候只能使用已有的异步库(asyncio等),功能有限。tcp

第三方协程模

1.greenlet模块ide

安装 : sudo pip3 install greenlet函数

函数spa

greenlet.greenlet(func)线程

  • 功能:建立协程对象
  • 参数:协程函数

g.switch()

  • 功能:选择要执行的协程函数
 1 from greenlet import greenlet  2 
 3 def test1():  4   print("执行test1")  5  gr2.switch()  6   print("结束test1")  7  gr2.switch()  8 
 9 def test2(): 10   print("执行test2") 11  gr1.switch() 12   print("结束test2") 13 
14 # 将函数变成协程
15 gr1 = greenlet(test1) 16 gr2 = greenlet(test2) 17 gr1.switch()  # 选择执行协程1
协程运行形态示例

2.gevent模块

安装:sudo pip3 install gevent

函数

gevent.spawn(func,argv)

  • 功能: 生成协程对象
  • 参数:
    • func 协程函数
    • argv 给协程函数传参(不定参)

返回值: 协程对象

gevent.joinall(list,[timeout])

  • 功能: 阻塞等待协程执行完毕
  • 参数:
    • list 协程对象列表
    • timeout 超时时间

gevent.sleep(sec)

  • 功能: gevent睡眠阻塞
  • 参数:睡眠时间

gevent协程只有在遇到gevent指定的阻塞行为时才会自动在协程之间进行跳转

如gevent.joinall(),gevent.sleep()带来的阻塞

 1 import gevent  2 
 3 
 4 # 协程函数
 5 def foo(a,b):  6   print("Running foo ...",a,b)  7   gevent.sleep(2)  8   print("Foo again")  9 
10 def bar(): 11   print("Running bar ...") 12   gevent.sleep(3) 13   print("bar again") 14 
15 f = gevent.spawn(foo,1,2) 16 b = gevent.spawn(bar) 17 
18 gevent.joinall([f,b]) # 阻塞等待[]中的协成结束
gevent 协程示例
 1 """
 2 扩展代码  3 """
 4 
 5 import gevent  6 from gevent import monkey  7 monkey.patch_all()  # 在导入socket前执行
 8 from socket import *
 9 
10 # 处理客户端请求
11 def handle(c): 12   while True: 13     data = c.recv(1024) 14     if not data: 15       break
16     print(data.decode()) 17     c.send(b'OK') 18  c.close() 19 
20 # 建立TCP套接字
21 s = socket() 22 s.bind(('0.0.0.0',8888)) 23 s.listen(5) 24 while True: 25   c,addr = s.accept() 26   print("Connect from",addr) 27   # handle(c) # 循环方案
28   gevent.spawn(handle,c)  # 协程方案
29 
30 s.close()
基于协程的tcp并发

monkey脚本

做用:在gevent协程中,协程只有遇到gevent指定类型的阻塞才能跳转到其余协程,所以,咱们但愿将普通的IO阻塞行为转换为能够触发gevent协程跳转的阻塞,以提升执行效率。

转换方法:gevent 提供了一个脚本程序monkey,能够修改底层解释IO阻塞的行为,将不少普通阻塞转换为gevent阻塞。

使用方法:

1.导入monkey

  from gevent import monkey

2.运行相应的脚本,例如转换socket中全部阻塞

  monkey.patch_socket()

3. 若是将全部可转换的IO阻塞所有转换则运行all

  monkey.patch_all()

注意:脚本运行函数须要在对应模块导入前执行

相关文章
相关标签/搜索